~ubuntu-branches/ubuntu/trusty/conntrack/trusty-proposed

« back to all changes in this revision

Viewing changes to src/netlink.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Wirt, Max Kellermann
  • Date: 2008-04-14 23:09:22 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080414230922-9xoi1gl38tc8lyng
Tags: 1:0.9.6-4
[ Max Kellermann ]
fix compilation on SPARC (printf argument mismatch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
 */
 
18
 
 
19
#include "netlink.h"
 
20
#include "conntrackd.h"
 
21
#include "traffic_stats.h"
 
22
#include "ignore.h"
 
23
#include "log.h"
 
24
#include "debug.h"
 
25
 
 
26
int ignore_conntrack(struct nf_conntrack *ct)
 
27
{
 
28
        /* ignore a certain protocol */
 
29
        if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)])
 
30
                return 1;
 
31
 
 
32
        /* Accept DNAT'ed traffic: not really coming to the local machine */
 
33
        if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) {
 
34
                debug_ct(ct, "DNAT");
 
35
                return 0;
 
36
        }
 
37
 
 
38
        /* Accept SNAT'ed traffic: not really coming to the local machine */
 
39
        if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) {
 
40
                debug_ct(ct, "SNAT");
 
41
                return 0;
 
42
        }
 
43
 
 
44
        /* Ignore traffic */
 
45
        if (ignore_pool_test(STATE(ignore_pool), ct)) {
 
46
                debug_ct(ct, "ignore traffic");
 
47
                return 1;
 
48
        }
 
49
 
 
50
        return 0;
 
51
}
 
52
 
 
53
static int event_handler(enum nf_conntrack_msg_type type,
 
54
                         struct nf_conntrack *ct,
 
55
                         void *data)
 
56
{
 
57
        /*
 
58
         * Ignore this conntrack: it talks about a
 
59
         * connection that is not interesting for us.
 
60
         */
 
61
        if (ignore_conntrack(ct))
 
62
                return NFCT_CB_STOP;
 
63
 
 
64
        switch(type) {
 
65
        case NFCT_T_NEW:
 
66
                STATE(mode)->event_new(ct);
 
67
                break;
 
68
        case NFCT_T_UPDATE:
 
69
                STATE(mode)->event_upd(ct);
 
70
                break;
 
71
        case NFCT_T_DESTROY:
 
72
                if (STATE(mode)->event_dst(ct))
 
73
                        update_traffic_stats(ct);
 
74
                break;
 
75
        default:
 
76
                dlog(LOG_WARNING, "unknown msg from ctnetlink\n");
 
77
                break;
 
78
        }
 
79
 
 
80
        return NFCT_CB_CONTINUE;
 
81
}
 
82
 
 
83
#include <sys/types.h>
 
84
#include <sys/socket.h>
 
85
#include <sys/fcntl.h>
 
86
 
 
87
int nl_init_event_handler(void)
 
88
{
 
89
        STATE(event) = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS);
 
90
        if (!STATE(event))
 
91
                return -1;
 
92
 
 
93
        fcntl(nfct_fd(STATE(event)), F_SETFL, O_NONBLOCK);
 
94
 
 
95
        /* set up socket buffer size */
 
96
        if (CONFIG(netlink_buffer_size))
 
97
                nfnl_rcvbufsiz(nfct_nfnlh(STATE(event)),
 
98
                               CONFIG(netlink_buffer_size));
 
99
        else {
 
100
                socklen_t socklen = sizeof(unsigned int);
 
101
                unsigned int read_size;
 
102
 
 
103
                /* get current buffer size */
 
104
                getsockopt(nfct_fd(STATE(event)), SOL_SOCKET,
 
105
                           SO_RCVBUF, &read_size, &socklen);
 
106
 
 
107
                CONFIG(netlink_buffer_size) = read_size;
 
108
        }
 
109
 
 
110
        /* ensure that maximum grown size is >= than maximum size */
 
111
        if (CONFIG(netlink_buffer_size_max_grown) < CONFIG(netlink_buffer_size))
 
112
                CONFIG(netlink_buffer_size_max_grown) =
 
113
                                        CONFIG(netlink_buffer_size);
 
114
 
 
115
        /* register callback for events */
 
116
        nfct_callback_register(STATE(event), NFCT_T_ALL, event_handler, NULL);
 
117
 
 
118
        return 0;
 
119
}
 
120
 
 
121
static int dump_handler(enum nf_conntrack_msg_type type,
 
122
                        struct nf_conntrack *ct,
 
123
                        void *data)
 
124
{
 
125
        /*
 
126
         * Ignore this conntrack: it talks about a
 
127
         * connection that is not interesting for us.
 
128
         */
 
129
        if (ignore_conntrack(ct))
 
130
                return NFCT_CB_CONTINUE;
 
131
 
 
132
        switch(type) {
 
133
        case NFCT_T_UPDATE:
 
134
                STATE(mode)->dump(ct);
 
135
                break;
 
136
        default:
 
137
                dlog(LOG_WARNING, "unknown msg from ctnetlink");
 
138
                break;
 
139
        }
 
140
        return NFCT_CB_CONTINUE;
 
141
}
 
142
 
 
143
int nl_init_dump_handler(void)
 
144
{
 
145
        /* open dump netlink socket */
 
146
        STATE(dump) = nfct_open(CONNTRACK, 0);
 
147
        if (!STATE(dump))
 
148
                return -1;
 
149
 
 
150
        /* register callback for dumped entries */
 
151
        nfct_callback_register(STATE(dump), NFCT_T_ALL, dump_handler, NULL);
 
152
 
 
153
        if (nl_dump_conntrack_table() == -1)
 
154
                return -1;
 
155
 
 
156
        return 0;
 
157
}
 
158
 
 
159
static int warned = 0;
 
160
 
 
161
void nl_resize_socket_buffer(struct nfct_handle *h)
 
162
{
 
163
        unsigned int s = CONFIG(netlink_buffer_size) * 2;
 
164
 
 
165
        /* already warned that we have reached the maximum buffer size */
 
166
        if (warned)
 
167
                return;
 
168
 
 
169
        if (s > CONFIG(netlink_buffer_size_max_grown)) {
 
170
                dlog(LOG_WARNING,
 
171
                     "maximum netlink socket buffer "
 
172
                     "size has been reached. We are likely to "
 
173
                     "be losing events, this may lead to "
 
174
                     "unsynchronized replicas. Please, consider "
 
175
                     "increasing netlink socket buffer size via "
 
176
                     "SocketBufferSize and "
 
177
                     "SocketBufferSizeMaxGrown clauses in "
 
178
                     "conntrackd.conf");
 
179
                s = CONFIG(netlink_buffer_size_max_grown);
 
180
                warned = 1;
 
181
        }
 
182
 
 
183
        CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s);
 
184
 
 
185
        /* notify the sysadmin */
 
186
        dlog(LOG_NOTICE, "netlink socket buffer size "
 
187
                         "has been set to %u bytes",
 
188
                         CONFIG(netlink_buffer_size));
 
189
}
 
190
 
 
191
int nl_dump_conntrack_table(void)
 
192
{
 
193
        return nfct_query(STATE(dump), NFCT_Q_DUMP, &CONFIG(family));
 
194
}
 
195
 
 
196
/* This function modifies the conntrack passed as argument! */
 
197
int nl_create_conntrack(struct nf_conntrack *ct)
 
198
{
 
199
        uint8_t flags;
 
200
 
 
201
        /* XXX: related connections */
 
202
        if (nfct_attr_is_set(ct, ATTR_STATUS)) {
 
203
                uint32_t status = nfct_get_attr_u32(ct, ATTR_STATUS);
 
204
                status &= ~IPS_EXPECTED;
 
205
                nfct_set_attr_u32(ct, ATTR_STATUS, status);
 
206
        }
 
207
 
 
208
        nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY);
 
209
 
 
210
        /*
 
211
         * TCP flags to overpass window tracking for recovered connections
 
212
         */
 
213
        flags = IP_CT_TCP_FLAG_BE_LIBERAL | IP_CT_TCP_FLAG_SACK_PERM;
 
214
        nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
 
215
        nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
 
216
        nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
 
217
        nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
 
218
 
 
219
        return nfct_query(STATE(dump), NFCT_Q_CREATE_UPDATE, ct);
 
220
}
 
221
 
 
222
int nl_destroy_conntrack(struct nf_conntrack *ct)
 
223
{
 
224
        return nfct_query(STATE(dump), NFCT_Q_DESTROY, ct);
 
225
}