1 /*
2 * lib/netfilter/ct.c Conntrack
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 * Copyright (c= 2008 Patrick McHardy <kaber@trash.net>
13 */
14
15 /**
16 * @ingroup nfnl
17 * @defgroup ct Conntrack
18 * @brief
19 * @{
20 */
21
22 #include <byteswap.h>
23 #include <sys/types.h>
24 #include <linux/netfilter/nfnetlink_conntrack.h>
25
26 #include <netlink-private/netlink.h>
27 #include <netlink/attr.h>
28 #include <netlink/netfilter/nfnl.h>
29 #include <netlink/netfilter/ct.h>
30
31 static struct nl_cache_ops nfnl_ct_ops;
32
33 #if __BYTE_ORDER == __BIG_ENDIAN
ntohll(uint64_t x)34 static uint64_t ntohll(uint64_t x)
35 {
36 return x;
37 }
htonll(uint64_t x)38 static uint64_t htonll(uint64_t x)
39 {
40 return x;
41 }
42 #elif __BYTE_ORDER == __LITTLE_ENDIAN
ntohll(uint64_t x)43 static uint64_t ntohll(uint64_t x)
44 {
45 return bswap_64(x);
46 }
htonll(uint64_t x)47 static uint64_t htonll(uint64_t x)
48 {
49 return bswap_64(x);
50 }
51 #endif
52
53 static struct nla_policy ct_policy[CTA_MAX+1] = {
54 [CTA_TUPLE_ORIG] = { .type = NLA_NESTED },
55 [CTA_TUPLE_REPLY] = { .type = NLA_NESTED },
56 [CTA_STATUS] = { .type = NLA_U32 },
57 [CTA_PROTOINFO] = { .type = NLA_NESTED },
58 //[CTA_HELP]
59 //[CTA_NAT_SRC]
60 [CTA_TIMEOUT] = { .type = NLA_U32 },
61 [CTA_MARK] = { .type = NLA_U32 },
62 [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED },
63 [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED },
64 [CTA_USE] = { .type = NLA_U32 },
65 [CTA_ID] = { .type = NLA_U32 },
66 [CTA_ZONE] = { .type = NLA_U16 },
67 //[CTA_NAT_DST]
68 };
69
70 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
71 [CTA_TUPLE_IP] = { .type = NLA_NESTED },
72 [CTA_TUPLE_PROTO] = { .type = NLA_NESTED },
73 };
74
75 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
76 [CTA_IP_V4_SRC] = { .type = NLA_U32 },
77 [CTA_IP_V4_DST] = { .type = NLA_U32 },
78 [CTA_IP_V6_SRC] = { .minlen = 16 },
79 [CTA_IP_V6_DST] = { .minlen = 16 },
80 };
81
82 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
83 [CTA_PROTO_NUM] = { .type = NLA_U8 },
84 [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
85 [CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
86 [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
87 [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 },
88 [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 },
89 [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 },
90 [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 },
91 [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 },
92 };
93
94 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
95 [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED },
96 };
97
98 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
99 [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 },
100 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 },
101 [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 },
102 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 },
103 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 },
104
105 };
106
107 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
108 [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 },
109 [CTA_COUNTERS_BYTES] = { .type = NLA_U64 },
110 [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 },
111 [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 },
112 };
113
114 static struct nla_policy ct_timestamp_policy[CTA_TIMESTAMP_MAX + 1] = {
115 [CTA_TIMESTAMP_START] = { .type = NLA_U64 },
116 [CTA_TIMESTAMP_STOP] = { .type = NLA_U64 },
117 };
118
ct_parse_ip(struct nfnl_ct * ct,int repl,struct nlattr * attr)119 static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
120 {
121 struct nlattr *tb[CTA_IP_MAX+1];
122 struct nl_addr *addr;
123 int err;
124
125 err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
126 if (err < 0)
127 goto errout;
128
129 if (tb[CTA_IP_V4_SRC]) {
130 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
131 if (addr == NULL)
132 goto errout_enomem;
133 err = nfnl_ct_set_src(ct, repl, addr);
134 nl_addr_put(addr);
135 if (err < 0)
136 goto errout;
137 }
138 if (tb[CTA_IP_V4_DST]) {
139 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
140 if (addr == NULL)
141 goto errout_enomem;
142 err = nfnl_ct_set_dst(ct, repl, addr);
143 nl_addr_put(addr);
144 if (err < 0)
145 goto errout;
146 }
147 if (tb[CTA_IP_V6_SRC]) {
148 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
149 if (addr == NULL)
150 goto errout_enomem;
151 err = nfnl_ct_set_src(ct, repl, addr);
152 nl_addr_put(addr);
153 if (err < 0)
154 goto errout;
155 }
156 if (tb[CTA_IP_V6_DST]) {
157 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
158 if (addr == NULL)
159 goto errout_enomem;
160 err = nfnl_ct_set_dst(ct, repl, addr);
161 nl_addr_put(addr);
162 if (err < 0)
163 goto errout;
164 }
165
166 return 0;
167
168 errout_enomem:
169 err = -NLE_NOMEM;
170 errout:
171 return err;
172 }
173
ct_parse_proto(struct nfnl_ct * ct,int repl,struct nlattr * attr)174 static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
175 {
176 struct nlattr *tb[CTA_PROTO_MAX+1];
177 int err;
178
179 err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
180 if (err < 0)
181 return err;
182
183 if (!repl && tb[CTA_PROTO_NUM])
184 nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
185 if (tb[CTA_PROTO_SRC_PORT])
186 nfnl_ct_set_src_port(ct, repl,
187 ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])));
188 if (tb[CTA_PROTO_DST_PORT])
189 nfnl_ct_set_dst_port(ct, repl,
190 ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));
191
192 if (ct->ct_family == AF_INET) {
193 if (tb[CTA_PROTO_ICMP_ID])
194 nfnl_ct_set_icmp_id(ct, repl,
195 ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
196 if (tb[CTA_PROTO_ICMP_TYPE])
197 nfnl_ct_set_icmp_type(ct, repl,
198 nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
199 if (tb[CTA_PROTO_ICMP_CODE])
200 nfnl_ct_set_icmp_code(ct, repl,
201 nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
202 } else if (ct->ct_family == AF_INET6) {
203 if (tb[CTA_PROTO_ICMPV6_ID])
204 nfnl_ct_set_icmp_id(ct, repl,
205 ntohs(nla_get_u16(tb[CTA_PROTO_ICMPV6_ID])));
206 if (tb[CTA_PROTO_ICMPV6_TYPE])
207 nfnl_ct_set_icmp_type(ct, repl,
208 nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]));
209 if (tb[CTA_PROTO_ICMPV6_CODE])
210 nfnl_ct_set_icmp_code(ct, repl,
211 nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]));
212 }
213
214 return 0;
215 }
216
ct_parse_tuple(struct nfnl_ct * ct,int repl,struct nlattr * attr)217 static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
218 {
219 struct nlattr *tb[CTA_TUPLE_MAX+1];
220 int err;
221
222 err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
223 if (err < 0)
224 return err;
225
226 if (tb[CTA_TUPLE_IP]) {
227 err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
228 if (err < 0)
229 return err;
230 }
231
232 if (tb[CTA_TUPLE_PROTO]) {
233 err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
234 if (err < 0)
235 return err;
236 }
237
238 return 0;
239 }
240
ct_parse_protoinfo_tcp(struct nfnl_ct * ct,struct nlattr * attr)241 static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
242 {
243 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
244 int err;
245
246 err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
247 ct_protoinfo_tcp_policy);
248 if (err < 0)
249 return err;
250
251 if (tb[CTA_PROTOINFO_TCP_STATE])
252 nfnl_ct_set_tcp_state(ct,
253 nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
254
255 return 0;
256 }
257
ct_parse_protoinfo(struct nfnl_ct * ct,struct nlattr * attr)258 static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
259 {
260 struct nlattr *tb[CTA_PROTOINFO_MAX+1];
261 int err;
262
263 err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
264 ct_protoinfo_policy);
265 if (err < 0)
266 return err;
267
268 if (tb[CTA_PROTOINFO_TCP]) {
269 err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
270 if (err < 0)
271 return err;
272 }
273
274 return 0;
275 }
276
ct_parse_counters(struct nfnl_ct * ct,int repl,struct nlattr * attr)277 static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
278 {
279 struct nlattr *tb[CTA_COUNTERS_MAX+1];
280 int err;
281
282 err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
283 if (err < 0)
284 return err;
285
286 if (tb[CTA_COUNTERS_PACKETS])
287 nfnl_ct_set_packets(ct, repl,
288 ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS])));
289 if (tb[CTA_COUNTERS32_PACKETS])
290 nfnl_ct_set_packets(ct, repl,
291 ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS])));
292 if (tb[CTA_COUNTERS_BYTES])
293 nfnl_ct_set_bytes(ct, repl,
294 ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES])));
295 if (tb[CTA_COUNTERS32_BYTES])
296 nfnl_ct_set_bytes(ct, repl,
297 ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES])));
298
299 return 0;
300 }
301
nfnlmsg_ct_group(struct nlmsghdr * nlh)302 int nfnlmsg_ct_group(struct nlmsghdr *nlh)
303 {
304 switch (nfnlmsg_subtype(nlh)) {
305 case IPCTNL_MSG_CT_NEW:
306 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
307 return NFNLGRP_CONNTRACK_NEW;
308 else
309 return NFNLGRP_CONNTRACK_UPDATE;
310 case IPCTNL_MSG_CT_DELETE:
311 return NFNLGRP_CONNTRACK_DESTROY;
312 default:
313 return NFNLGRP_NONE;
314 }
315 }
316
ct_parse_timestamp(struct nfnl_ct * ct,struct nlattr * attr)317 static int ct_parse_timestamp(struct nfnl_ct *ct, struct nlattr *attr)
318 {
319 struct nlattr *tb[CTA_TIMESTAMP_MAX + 1];
320 int err;
321
322 err = nla_parse_nested(tb, CTA_TIMESTAMP_MAX, attr,
323 ct_timestamp_policy);
324 if (err < 0)
325 return err;
326
327 if (tb[CTA_TIMESTAMP_START] && tb[CTA_TIMESTAMP_STOP])
328 nfnl_ct_set_timestamp(ct,
329 ntohll(nla_get_u64(tb[CTA_TIMESTAMP_START])),
330 ntohll(nla_get_u64(tb[CTA_TIMESTAMP_STOP])));
331
332 return 0;
333 }
334
nfnlmsg_ct_parse(struct nlmsghdr * nlh,struct nfnl_ct ** result)335 int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result)
336 {
337 struct nfnl_ct *ct;
338 struct nlattr *tb[CTA_MAX+1];
339 int err;
340
341 ct = nfnl_ct_alloc();
342 if (!ct)
343 return -NLE_NOMEM;
344
345 ct->ce_msgtype = nlh->nlmsg_type;
346
347 err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
348 ct_policy);
349 if (err < 0)
350 goto errout;
351
352 nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
353
354 if (tb[CTA_TUPLE_ORIG]) {
355 err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
356 if (err < 0)
357 goto errout;
358 }
359 if (tb[CTA_TUPLE_REPLY]) {
360 err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
361 if (err < 0)
362 goto errout;
363 }
364
365 if (tb[CTA_PROTOINFO]) {
366 err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
367 if (err < 0)
368 goto errout;
369 }
370
371 if (tb[CTA_STATUS])
372 nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
373 if (tb[CTA_TIMEOUT])
374 nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
375 if (tb[CTA_MARK])
376 nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
377 if (tb[CTA_USE])
378 nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
379 if (tb[CTA_ID])
380 nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
381 if (tb[CTA_ZONE])
382 nfnl_ct_set_zone(ct, ntohs(nla_get_u16(tb[CTA_ZONE])));
383
384 if (tb[CTA_COUNTERS_ORIG]) {
385 err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
386 if (err < 0)
387 goto errout;
388 }
389
390 if (tb[CTA_COUNTERS_REPLY]) {
391 err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
392 if (err < 0)
393 goto errout;
394 }
395
396 if (tb[CTA_TIMESTAMP]) {
397 err = ct_parse_timestamp(ct, tb[CTA_TIMESTAMP]);
398 if (err < 0)
399 goto errout;
400 }
401
402 *result = ct;
403 return 0;
404
405 errout:
406 nfnl_ct_put(ct);
407 return err;
408 }
409
ct_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)410 static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
411 struct nlmsghdr *nlh, struct nl_parser_param *pp)
412 {
413 struct nfnl_ct *ct;
414 int err;
415
416 if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
417 return err;
418
419 err = pp->pp_cb((struct nl_object *) ct, pp);
420 nfnl_ct_put(ct);
421 return err;
422 }
423
nfnl_ct_dump_request(struct nl_sock * sk)424 int nfnl_ct_dump_request(struct nl_sock *sk)
425 {
426 return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
427 NLM_F_DUMP, AF_UNSPEC, 0);
428 }
429
ct_request_update(struct nl_cache * cache,struct nl_sock * sk)430 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
431 {
432 return nfnl_ct_dump_request(sk);
433 }
434
nfnl_ct_build_tuple(struct nl_msg * msg,const struct nfnl_ct * ct,int repl)435 static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
436 int repl)
437 {
438 struct nlattr *tuple, *ip, *proto;
439 struct nl_addr *addr;
440 int family;
441
442 family = nfnl_ct_get_family(ct);
443
444 tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
445 if (!tuple)
446 goto nla_put_failure;
447
448 ip = nla_nest_start(msg, CTA_TUPLE_IP);
449 if (!ip)
450 goto nla_put_failure;
451
452 addr = nfnl_ct_get_src(ct, repl);
453 if (addr)
454 NLA_PUT_ADDR(msg,
455 family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
456 addr);
457
458 addr = nfnl_ct_get_dst(ct, repl);
459 if (addr)
460 NLA_PUT_ADDR(msg,
461 family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
462 addr);
463
464 nla_nest_end(msg, ip);
465
466 proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
467 if (!proto)
468 goto nla_put_failure;
469
470 if (nfnl_ct_test_proto(ct))
471 NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
472
473 if (nfnl_ct_test_src_port(ct, repl))
474 NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
475 htons(nfnl_ct_get_src_port(ct, repl)));
476
477 if (nfnl_ct_test_dst_port(ct, repl))
478 NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
479 htons(nfnl_ct_get_dst_port(ct, repl)));
480
481 if (family == AF_INET) {
482 if (nfnl_ct_test_icmp_id(ct, repl))
483 NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
484 htons(nfnl_ct_get_icmp_id(ct, repl)));
485
486 if (nfnl_ct_test_icmp_type(ct, repl))
487 NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
488 nfnl_ct_get_icmp_type(ct, repl));
489
490 if (nfnl_ct_test_icmp_code(ct, repl))
491 NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
492 nfnl_ct_get_icmp_code(ct, repl));
493 } else if (family == AF_INET6) {
494 if (nfnl_ct_test_icmp_id(ct, repl))
495 NLA_PUT_U16(msg, CTA_PROTO_ICMPV6_ID,
496 htons(nfnl_ct_get_icmp_id(ct, repl)));
497
498 if (nfnl_ct_test_icmp_type(ct, repl))
499 NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_TYPE,
500 nfnl_ct_get_icmp_type(ct, repl));
501
502 if (nfnl_ct_test_icmp_code(ct, repl))
503 NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_CODE,
504 nfnl_ct_get_icmp_code(ct, repl));
505 }
506
507 nla_nest_end(msg, proto);
508
509 nla_nest_end(msg, tuple);
510 return 0;
511
512 nla_put_failure:
513 return -NLE_MSGSIZE;
514 }
515
nfnl_ct_build_message(const struct nfnl_ct * ct,int cmd,int flags,struct nl_msg ** result)516 static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
517 struct nl_msg **result)
518 {
519 struct nl_msg *msg;
520 int err;
521
522 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
523 nfnl_ct_get_family(ct), 0);
524 if (msg == NULL)
525 return -NLE_NOMEM;
526
527 if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
528 goto err_out;
529
530 /* REPLY tuple is optional, dont add unless at least src/dst specified */
531
532 if ( nfnl_ct_get_src(ct, 1) && nfnl_ct_get_dst(ct, 1) )
533 if ((err = nfnl_ct_build_tuple(msg, ct, 1)) < 0)
534 goto err_out;
535
536 if (nfnl_ct_test_status(ct))
537 NLA_PUT_U32(msg, CTA_STATUS, htonl(nfnl_ct_get_status(ct)));
538
539 if (nfnl_ct_test_timeout(ct))
540 NLA_PUT_U32(msg, CTA_TIMEOUT, htonl(nfnl_ct_get_timeout(ct)));
541
542 if (nfnl_ct_test_mark(ct))
543 NLA_PUT_U32(msg, CTA_MARK, htonl(nfnl_ct_get_mark(ct)));
544
545 if (nfnl_ct_test_id(ct))
546 NLA_PUT_U32(msg, CTA_ID, htonl(nfnl_ct_get_id(ct)));
547
548 if (nfnl_ct_test_zone(ct))
549 NLA_PUT_U16(msg, CTA_ZONE, htons(nfnl_ct_get_zone(ct)));
550
551 *result = msg;
552 return 0;
553
554 nla_put_failure:
555 err_out:
556 nlmsg_free(msg);
557 return err;
558 }
559
nfnl_ct_build_add_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)560 int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
561 struct nl_msg **result)
562 {
563 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
564 }
565
nfnl_ct_add(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)566 int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
567 {
568 struct nl_msg *msg;
569 int err;
570
571 if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
572 return err;
573
574 err = nl_send_auto_complete(sk, msg);
575 nlmsg_free(msg);
576 if (err < 0)
577 return err;
578
579 return wait_for_ack(sk);
580 }
581
nfnl_ct_build_delete_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)582 int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
583 struct nl_msg **result)
584 {
585 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
586 }
587
nfnl_ct_del(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)588 int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
589 {
590 struct nl_msg *msg;
591 int err;
592
593 if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
594 return err;
595
596 err = nl_send_auto_complete(sk, msg);
597 nlmsg_free(msg);
598 if (err < 0)
599 return err;
600
601 return wait_for_ack(sk);
602 }
603
nfnl_ct_build_query_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)604 int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
605 struct nl_msg **result)
606 {
607 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
608 }
609
nfnl_ct_query(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)610 int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
611 {
612 struct nl_msg *msg;
613 int err;
614
615 if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
616 return err;
617
618 err = nl_send_auto_complete(sk, msg);
619 nlmsg_free(msg);
620 if (err < 0)
621 return err;
622
623 return wait_for_ack(sk);
624 }
625
626 /**
627 * @name Cache Management
628 * @{
629 */
630
631 /**
632 * Build a conntrack cache holding all conntrack currently in the kernel
633 * @arg sk Netlink socket.
634 * @arg result Pointer to store resulting cache.
635 *
636 * Allocates a new cache, initializes it properly and updates it to
637 * contain all conntracks currently in the kernel.
638 *
639 * @return 0 on success or a negative error code.
640 */
nfnl_ct_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)641 int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
642 {
643 return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result);
644 }
645
646 /** @} */
647
648 /**
649 * @name Conntrack Addition
650 * @{
651 */
652
653 /** @} */
654
655 static struct nl_af_group ct_groups[] = {
656 { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
657 { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
658 { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
659 { END_OF_GROUP_LIST },
660 };
661
662 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
663 static struct nl_cache_ops nfnl_ct_ops = {
664 .co_name = "netfilter/ct",
665 .co_hdrsize = NFNL_HDRLEN,
666 .co_msgtypes = {
667 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
668 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
669 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
670 END_OF_MSGTYPES_LIST,
671 },
672 .co_protocol = NETLINK_NETFILTER,
673 .co_groups = ct_groups,
674 .co_request_update = ct_request_update,
675 .co_msg_parser = ct_msg_parser,
676 .co_obj_ops = &ct_obj_ops,
677 };
678
ct_init(void)679 static void __init ct_init(void)
680 {
681 nl_cache_mngt_register(&nfnl_ct_ops);
682 }
683
ct_exit(void)684 static void __exit ct_exit(void)
685 {
686 nl_cache_mngt_unregister(&nfnl_ct_ops);
687 }
688
689 /** @} */
690