libnl  1.1
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 
29 static struct nl_cache_ops nfnl_log_ops;
30 
31 #if __BYTE_ORDER == __BIG_ENDIAN
32 static uint64_t ntohll(uint64_t x)
33 {
34  return x;
35 }
36 #elif __BYTE_ORDER == __LITTLE_ENDIAN
37 static uint64_t ntohll(uint64_t x)
38 {
39  return __bswap_64(x);
40 }
41 #endif
42 
43 static 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 
65 struct 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 
158 errout:
159  nfnl_log_put(log);
160  return NULL;
161 }
162 
163 static 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 
179 errout:
180  nfnl_log_put(log);
181  return err;
182 
183 errout_errno:
184  err = nl_get_errno();
185  goto errout;
186 }
187 
188 /**
189  * @name Log Commands
190  * @{
191  */
192 
193 static 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 
210 nla_put_failure:
211  nlmsg_free(msg);
212  return NULL;
213 }
214 
215 static 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 
227 struct nl_msg *nfnl_log_build_bind(uint16_t queuenum)
228 {
229  return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_BIND);
230 }
231 
232 int 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 
243 struct nl_msg *nfnl_log_build_unbind(uint16_t queuenum)
244 {
245  return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_UNBIND);
246 }
247 
248 int 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 
259 struct 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 
264 int 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 
275 struct 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 
280 int 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 
291 struct 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 
309 nla_put_failure:
310  nlmsg_free(msg);
311  return NULL;
312 }
313 
314 int 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))
328 static 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 
340 static void __init log_init(void)
341 {
342  nl_cache_mngt_register(&nfnl_log_ops);
343 }
344 
345 static void __exit log_exit(void)
346 {
347  nl_cache_mngt_unregister(&nfnl_log_ops);
348 }
349 
350 /** @} */
32bit integer
Definition: attr.h:39
uint16_t nlmsg_type
Message type (content type)
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:157
attribute validation policy
Definition: attr.h:73
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
Definition: nl.c:800
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:659
Netlink message header.
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
character string
Definition: attr.h:41
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_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:127
Cache Operations.
Definition: cache-api.h:163
void * nla_data(const struct nlattr *nla)
head of payload
Definition: attr.c:151
int nla_len(const struct nlattr *nla)
length of payload
Definition: attr.c:160
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
Definition: nfnl.c:150
uint16_t minlen
Minimal length of payload required to be available.
Definition: attr.h:78
Netlink socket address.
Definition: netlink-kernel.h:8
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:512
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
Definition: attr.c:694
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