Tizen 2.1 base
[platform/upstream/libnl2.git] / lib / netfilter / 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-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 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 /**
30  * @name Log Commands
31  * @{
32  */
33
34 static int build_log_cmd_request(uint8_t family, uint16_t queuenum,
35                                  uint8_t command, struct nl_msg **result)
36 {
37         struct nl_msg *msg;
38         struct nfulnl_msg_config_cmd cmd;
39
40         msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
41                                    family, queuenum);
42         if (msg == NULL)
43                 return -NLE_NOMEM;
44
45         cmd.command = command;
46         if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
47                 goto nla_put_failure;
48
49         *result = msg;
50         return 0;
51
52 nla_put_failure:
53         nlmsg_free(msg);
54         return -NLE_MSGSIZE;
55 }
56
57 static int send_log_request(struct nl_sock *sk, struct nl_msg *msg)
58 {
59         int err;
60
61         err = nl_send_auto_complete(sk, msg);
62         nlmsg_free(msg);
63         if (err < 0)
64                 return err;
65
66         return wait_for_ack(sk);
67 }
68
69 int nfnl_log_build_pf_bind(uint8_t pf, struct nl_msg **result)
70 {
71         return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_BIND, result);
72 }
73
74 int nfnl_log_pf_bind(struct nl_sock *nlh, uint8_t pf)
75 {
76         struct nl_msg *msg;
77         int err;
78
79         if ((err = nfnl_log_build_pf_bind(pf, &msg)) < 0)
80                 return err;
81
82         return send_log_request(nlh, msg);
83 }
84
85 int nfnl_log_build_pf_unbind(uint8_t pf, struct nl_msg **result)
86 {
87         return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_UNBIND, result);
88 }
89
90 int nfnl_log_pf_unbind(struct nl_sock *nlh, uint8_t pf)
91 {
92         struct nl_msg *msg;
93         int err;
94
95         if ((err = nfnl_log_build_pf_unbind(pf, &msg)) < 0)
96                 return err;
97
98         return send_log_request(nlh, msg);
99 }
100
101 static int nfnl_log_build_request(const struct nfnl_log *log,
102                                   struct nl_msg **result)
103 {
104         struct nl_msg *msg;
105
106         if (!nfnl_log_test_group(log))
107                 return -NLE_MISSING_ATTR;
108
109         msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
110                                    0, nfnl_log_get_group(log));
111         if (msg == NULL)
112                 return -NLE_NOMEM;
113
114         /* This sucks. The nfnetlink_log interface always expects both
115          * parameters to be present. Needs to be done properly.
116          */
117         if (nfnl_log_test_copy_mode(log)) {
118                 struct nfulnl_msg_config_mode mode;
119
120                 switch (nfnl_log_get_copy_mode(log)) {
121                 case NFNL_LOG_COPY_NONE:
122                         mode.copy_mode = NFULNL_COPY_NONE;
123                         break;
124                 case NFNL_LOG_COPY_META:
125                         mode.copy_mode = NFULNL_COPY_META;
126                         break;
127                 case NFNL_LOG_COPY_PACKET:
128                         mode.copy_mode = NFULNL_COPY_PACKET;
129                         break;
130                 }
131                 mode.copy_range = htonl(nfnl_log_get_copy_range(log));
132                 mode._pad = 0;
133
134                 if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0)
135                         goto nla_put_failure;
136         }
137
138         if (nfnl_log_test_flush_timeout(log) &&
139             nla_put_u32(msg, NFULA_CFG_TIMEOUT,
140                         htonl(nfnl_log_get_flush_timeout(log))) < 0)
141                 goto nla_put_failure;
142
143         if (nfnl_log_test_alloc_size(log) &&
144             nla_put_u32(msg, NFULA_CFG_NLBUFSIZ,
145                         htonl(nfnl_log_get_alloc_size(log))) < 0)
146                 goto nla_put_failure;
147
148         if (nfnl_log_test_queue_threshold(log) &&
149             nla_put_u32(msg, NFULA_CFG_QTHRESH,
150                         htonl(nfnl_log_get_queue_threshold(log))) < 0)
151                 goto nla_put_failure;
152
153         *result = msg;
154         return 0;
155
156 nla_put_failure:
157         nlmsg_free(msg);
158         return -NLE_MSGSIZE;
159 }
160
161 int nfnl_log_build_create_request(const struct nfnl_log *log,
162                                   struct nl_msg **result)
163 {
164         struct nfulnl_msg_config_cmd cmd;
165         int err;
166
167         if ((err = nfnl_log_build_request(log, result)) < 0)
168                 return err;
169
170         cmd.command = NFULNL_CFG_CMD_BIND;
171
172         if (nla_put(*result, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
173                 goto nla_put_failure;
174
175         return 0;
176
177 nla_put_failure:
178         nlmsg_free(*result);
179         return -NLE_MSGSIZE;
180 }
181
182 int nfnl_log_create(struct nl_sock *nlh, const struct nfnl_log *log)
183 {
184         struct nl_msg *msg;
185         int err;
186
187         if ((err = nfnl_log_build_create_request(log, &msg)) < 0)
188                 return err;
189
190         return send_log_request(nlh, msg);
191 }
192
193 int nfnl_log_build_change_request(const struct nfnl_log *log,
194                                   struct nl_msg **result)
195 {
196         return nfnl_log_build_request(log, result);
197 }
198
199 int nfnl_log_change(struct nl_sock *nlh, const struct nfnl_log *log)
200 {
201         struct nl_msg *msg;
202         int err;
203
204         if ((err = nfnl_log_build_change_request(log, &msg)) < 0)
205                 return err;
206
207         return send_log_request(nlh, msg);
208 }
209
210 int nfnl_log_build_delete_request(const struct nfnl_log *log,
211                                   struct nl_msg **result)
212 {
213         if (!nfnl_log_test_group(log))
214                 return -NLE_MISSING_ATTR;
215
216         return build_log_cmd_request(0, nfnl_log_get_group(log),
217                                      NFULNL_CFG_CMD_UNBIND, result);
218 }
219
220 int nfnl_log_delete(struct nl_sock *nlh, const struct nfnl_log *log)
221 {
222         struct nl_msg *msg;
223         int err;
224
225         if ((err = nfnl_log_build_delete_request(log, &msg)) < 0)
226                 return err;
227
228         return send_log_request(nlh, msg);
229 }
230
231 /** @} */
232
233 static struct nl_cache_ops nfnl_log_ops = {
234         .co_name                = "netfilter/log",
235         .co_obj_ops             = &log_obj_ops,
236         .co_msgtypes            = {
237                 END_OF_MSGTYPES_LIST,
238         },
239 };
240
241 static void __init log_init(void)
242 {
243         nl_cache_mngt_register(&nfnl_log_ops);
244 }
245
246 static void __exit log_exit(void)
247 {
248         nl_cache_mngt_unregister(&nfnl_log_ops);
249 }
250
251 /** @} */