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