19
19
#include "netlink.h"
20
20
#include "conntrackd.h"
21
#include "traffic_stats.h"
28
int ignore_conntrack(struct nf_conntrack *ct)
30
/* ignore a certain protocol */
31
if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)])
34
/* Accept DNAT'ed traffic: not really coming to the local machine */
35
if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) {
40
/* Accept SNAT'ed traffic: not really coming to the local machine */
41
if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) {
47
if (ignore_pool_test(STATE(ignore_pool), ct)) {
48
debug_ct(ct, "ignore traffic");
55
static int event_handler(enum nf_conntrack_msg_type type,
56
struct nf_conntrack *ct,
60
* Ignore this conntrack: it talks about a
61
* connection that is not interesting for us.
63
if (ignore_conntrack(ct))
68
STATE(mode)->event_new(ct);
71
STATE(mode)->event_upd(ct);
74
if (STATE(mode)->event_dst(ct))
75
update_traffic_stats(ct);
78
dlog(LOG_WARNING, "unknown msg from ctnetlink\n");
82
return NFCT_CB_CONTINUE;
85
26
#include <sys/types.h>
86
27
#include <sys/socket.h>
87
28
#include <sys/fcntl.h>
29
#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
89
int nl_init_event_handler(void)
31
struct nfct_handle *nl_init_event_handler(void)
91
STATE(event) = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS);
95
fcntl(nfct_fd(STATE(event)), F_SETFL, O_NONBLOCK);
33
struct nfct_handle *h;
35
h = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS);
40
if (CONFIG(filter_from_kernelspace)) {
41
if (nfct_filter_attach(nfct_fd(h),
42
STATE(filter)) == -1) {
43
dlog(LOG_ERR, "cannot set event filtering: %s",
46
dlog(LOG_NOTICE, "using kernel-space event filtering");
48
dlog(LOG_NOTICE, "using user-space event filtering");
50
nfct_filter_destroy(STATE(filter));
53
fcntl(nfct_fd(h), F_SETFL, O_NONBLOCK);
97
55
/* set up socket buffer size */
98
if (CONFIG(netlink_buffer_size))
99
nfnl_rcvbufsiz(nfct_nfnlh(STATE(event)),
100
CONFIG(netlink_buffer_size));
56
if (CONFIG(netlink_buffer_size)) {
57
CONFIG(netlink_buffer_size) =
58
nfnl_rcvbufsiz(nfct_nfnlh(h), CONFIG(netlink_buffer_size));
102
60
socklen_t socklen = sizeof(unsigned int);
103
61
unsigned int read_size;
105
63
/* get current buffer size */
106
getsockopt(nfct_fd(STATE(event)), SOL_SOCKET,
64
getsockopt(nfct_fd(h), SOL_SOCKET,
107
65
SO_RCVBUF, &read_size, &socklen);
109
67
CONFIG(netlink_buffer_size) = read_size;
70
dlog(LOG_NOTICE, "netlink event socket buffer size has been set "
71
"to %u bytes", CONFIG(netlink_buffer_size));
112
73
/* ensure that maximum grown size is >= than maximum size */
113
74
if (CONFIG(netlink_buffer_size_max_grown) < CONFIG(netlink_buffer_size))
114
75
CONFIG(netlink_buffer_size_max_grown) =
115
76
CONFIG(netlink_buffer_size);
117
/* register callback for events */
118
nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL);
123
static int dump_handler(enum nf_conntrack_msg_type type,
124
struct nf_conntrack *ct,
81
struct nlif_handle *nl_init_interface_handler(void)
128
* Ignore this conntrack: it talks about a
129
* connection that is not interesting for us.
131
if (ignore_conntrack(ct))
132
return NFCT_CB_CONTINUE;
83
struct nlif_handle *h;
136
STATE(mode)->dump(ct);
139
dlog(LOG_WARNING, "unknown msg from ctnetlink");
88
if (nlif_query(h) == -1) {
142
return NFCT_CB_CONTINUE;
145
int nl_init_dump_handler(void)
147
/* open dump netlink socket */
148
STATE(dump) = nfct_open(CONNTRACK, 0);
152
/* register callback for dumped entries */
153
nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL);
155
if (nl_dump_conntrack_table() == -1)
161
int nl_init_overrun_handler(void)
163
STATE(overrun) = nfct_open(CONNTRACK, 0);
167
fcntl(nfct_fd(STATE(overrun)), F_SETFL, O_NONBLOCK);
169
nfct_callback_register(STATE(overrun),
171
STATE(mode)->overrun,
92
fcntl(nlif_fd(h), F_SETFL, O_NONBLOCK);
176
97
static int warned = 0;
178
99
void nl_resize_socket_buffer(struct nfct_handle *h)
180
unsigned int s = CONFIG(netlink_buffer_size) * 2;
101
/* sock_setsockopt in net/core/sock.c doubles the size of the buffer */
102
unsigned int s = CONFIG(netlink_buffer_size);
182
104
/* already warned that we have reached the maximum buffer size */
200
122
CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s);
202
124
/* notify the sysadmin */
203
dlog(LOG_NOTICE, "netlink socket buffer size "
204
"has been set to %u bytes",
205
CONFIG(netlink_buffer_size));
208
int nl_dump_conntrack_table(void)
210
return nfct_query(STATE(dump), NFCT_Q_DUMP, &CONFIG(family));
213
int nl_overrun_request_resync(void)
125
dlog(LOG_NOTICE, "netlink socket buffer size has been increased "
126
"to %u bytes", CONFIG(netlink_buffer_size));
129
int nl_dump_conntrack_table(struct nfct_handle *h)
131
return nfct_query(h, NFCT_Q_DUMP, &CONFIG(family));
134
int nl_flush_conntrack_table(struct nfct_handle *h)
136
return nfct_query(h, NFCT_Q_FLUSH, &CONFIG(family));
139
int nl_send_resync(struct nfct_handle *h)
215
141
int family = CONFIG(family);
216
return nfct_send(STATE(overrun), NFCT_Q_DUMP, &family);
142
return nfct_send(h, NFCT_Q_DUMP, &family);
219
int nl_exist_conntrack(struct nf_conntrack *ct)
145
/* if the handle has no callback, check for existence, otherwise, update */
146
int nl_get_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct)
223
ret = nfct_query(STATE(dump), NFCT_Q_GET, ct);
149
char __tmp[nfct_maxsize()];
150
struct nf_conntrack *tmp = (struct nf_conntrack *) (void *)__tmp;
152
memset(__tmp, 0, sizeof(__tmp));
154
/* use the original tuple to check if it is there */
155
nfct_copy(tmp, ct, NFCT_CP_ORIG);
157
ret = nfct_query(h, NFCT_Q_GET, tmp);
225
159
return errno == ENOENT ? 0 : -1;
230
/* This function modifies the conntrack passed as argument! */
231
int nl_create_conntrack(struct nf_conntrack *ct)
164
int nl_create_conntrack(struct nfct_handle *h,
165
const struct nf_conntrack *orig,
235
/* XXX: related connections */
169
struct nf_conntrack *ct;
171
ct = nfct_clone(orig);
176
nfct_set_attr_u32(ct, ATTR_TIMEOUT, timeout);
178
/* we hit error if we try to change the expected bit */
236
179
if (nfct_attr_is_set(ct, ATTR_STATUS)) {
237
180
uint32_t status = nfct_get_attr_u32(ct, ATTR_STATUS);
238
181
status &= ~IPS_EXPECTED;
245
188
* TCP flags to overpass window tracking for recovered connections
247
flags = IP_CT_TCP_FLAG_BE_LIBERAL | IP_CT_TCP_FLAG_SACK_PERM;
248
nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
249
nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
250
nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
251
nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
253
return nfct_query(STATE(dump), NFCT_Q_CREATE_UPDATE, ct);
190
if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) {
191
uint8_t flags = IP_CT_TCP_FLAG_BE_LIBERAL |
192
IP_CT_TCP_FLAG_SACK_PERM;
194
/* FIXME: workaround, we should send TCP flags in updates */
195
if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >=
196
TCP_CONNTRACK_TIME_WAIT) {
197
flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
199
nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
200
nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
201
nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
202
nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
205
ret = nfct_query(h, NFCT_Q_CREATE, ct);
256
/* This function modifies the conntrack passed as argument! */
257
int nl_update_conntrack(struct nf_conntrack *ct)
211
int nl_update_conntrack(struct nfct_handle *h,
212
const struct nf_conntrack *orig,
216
struct nf_conntrack *ct;
218
ct = nfct_clone(orig);
223
nfct_set_attr_u32(ct, ATTR_TIMEOUT, timeout);
259
225
/* unset NAT info, otherwise we hit error */
260
226
nfct_attr_unset(ct, ATTR_SNAT_IPV4);
261
227
nfct_attr_unset(ct, ATTR_DNAT_IPV4);
267
233
status &= ~IPS_NAT_MASK;
268
234
nfct_set_attr_u32(ct, ATTR_STATUS, status);
271
return nl_create_conntrack(ct);
236
/* we have to unset the helper to avoid EBUSY in reset timers */
237
if (nfct_attr_is_set(ct, ATTR_HELPER_NAME))
238
nfct_attr_unset(ct, ATTR_HELPER_NAME);
240
/* we hit error if we try to update the master conntrack */
241
if (ct_is_related(ct)) {
242
nfct_attr_unset(ct, ATTR_MASTER_L3PROTO);
243
nfct_attr_unset(ct, ATTR_MASTER_L4PROTO);
244
nfct_attr_unset(ct, ATTR_MASTER_IPV4_SRC);
245
nfct_attr_unset(ct, ATTR_MASTER_IPV4_DST);
246
nfct_attr_unset(ct, ATTR_MASTER_IPV6_SRC);
247
nfct_attr_unset(ct, ATTR_MASTER_IPV6_DST);
248
nfct_attr_unset(ct, ATTR_MASTER_PORT_SRC);
249
nfct_attr_unset(ct, ATTR_MASTER_PORT_DST);
253
* TCP flags to overpass window tracking for recovered connections
255
if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) {
256
uint8_t flags = IP_CT_TCP_FLAG_BE_LIBERAL |
257
IP_CT_TCP_FLAG_SACK_PERM;
259
/* FIXME: workaround, we should send TCP flags in updates */
260
if (nfct_get_attr_u32(ct, ATTR_TCP_STATE) ==
261
TCP_CONNTRACK_TIME_WAIT) {
262
flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
264
nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
265
nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
266
nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
267
nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
270
ret = nfct_query(h, NFCT_Q_UPDATE, ct);
274
int nl_destroy_conntrack(struct nf_conntrack *ct)
276
int nl_destroy_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct)
276
return nfct_query(STATE(dump), NFCT_Q_DESTROY, ct);
278
return nfct_query(h, NFCT_Q_DESTROY, ct);