libnl 1.1.4
ct_obj.c
1/*
2 * lib/netfilter/ct_obj.c Conntrack Object
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-2006 Thomas Graf <tgraf@suug.ch>
10 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
11 * Copyright (c) 2007 Secure Computing Corporation
12 */
13
14#include <sys/types.h>
15#include <linux/netfilter/nfnetlink_conntrack.h>
16#include <linux/netfilter/nf_conntrack_common.h>
17#include <linux/netfilter/nf_conntrack_tcp.h>
18
19#include <netlink-local.h>
20#include <netlink/netfilter/nfnl.h>
21#include <netlink/netfilter/ct.h>
22
23/** @cond SKIP */
24#define CT_ATTR_FAMILY (1UL << 0)
25#define CT_ATTR_PROTO (1UL << 1)
26
27#define CT_ATTR_TCP_STATE (1UL << 2)
28
29#define CT_ATTR_STATUS (1UL << 3)
30#define CT_ATTR_TIMEOUT (1UL << 4)
31#define CT_ATTR_MARK (1UL << 5)
32#define CT_ATTR_USE (1UL << 6)
33#define CT_ATTR_ID (1UL << 7)
34
35#define CT_ATTR_ORIG_SRC (1UL << 8)
36#define CT_ATTR_ORIG_DST (1UL << 9)
37#define CT_ATTR_ORIG_SRC_PORT (1UL << 10)
38#define CT_ATTR_ORIG_DST_PORT (1UL << 11)
39#define CT_ATTR_ORIG_ICMP_ID (1UL << 12)
40#define CT_ATTR_ORIG_ICMP_TYPE (1UL << 13)
41#define CT_ATTR_ORIG_ICMP_CODE (1UL << 14)
42#define CT_ATTR_ORIG_PACKETS (1UL << 15)
43#define CT_ATTR_ORIG_BYTES (1UL << 16)
44
45#define CT_ATTR_REPL_SRC (1UL << 17)
46#define CT_ATTR_REPL_DST (1UL << 18)
47#define CT_ATTR_REPL_SRC_PORT (1UL << 19)
48#define CT_ATTR_REPL_DST_PORT (1UL << 20)
49#define CT_ATTR_REPL_ICMP_ID (1UL << 21)
50#define CT_ATTR_REPL_ICMP_TYPE (1UL << 22)
51#define CT_ATTR_REPL_ICMP_CODE (1UL << 23)
52#define CT_ATTR_REPL_PACKETS (1UL << 24)
53#define CT_ATTR_REPL_BYTES (1UL << 25)
54/** @endcond */
55
56static void ct_free_data(struct nl_object *c)
57{
58 struct nfnl_ct *ct = (struct nfnl_ct *) c;
59
60 if (ct == NULL)
61 return;
62
63 nl_addr_put(ct->ct_orig.src);
64 nl_addr_put(ct->ct_orig.dst);
65 nl_addr_put(ct->ct_repl.src);
66 nl_addr_put(ct->ct_repl.dst);
67}
68
69static int ct_clone(struct nl_object *_dst, struct nl_object *_src)
70{
71 struct nfnl_ct *dst = (struct nfnl_ct *) _dst;
72 struct nfnl_ct *src = (struct nfnl_ct *) _src;
73 struct nl_addr *addr;
74
75 if (src->ct_orig.src) {
76 addr = nl_addr_clone(src->ct_orig.src);
77 if (!addr)
78 goto errout;
79 dst->ct_orig.src = addr;
80 }
81
82 if (src->ct_orig.dst) {
83 addr = nl_addr_clone(src->ct_orig.dst);
84 if (!addr)
85 goto errout;
86 dst->ct_orig.dst = addr;
87 }
88
89 if (src->ct_repl.src) {
90 addr = nl_addr_clone(src->ct_repl.src);
91 if (!addr)
92 goto errout;
93 dst->ct_repl.src = addr;
94 }
95
96 if (src->ct_repl.dst) {
97 addr = nl_addr_clone(src->ct_repl.dst);
98 if (!addr)
99 goto errout;
100 dst->ct_repl.dst = addr;
101 }
102
103 return 0;
104errout:
105 return nl_get_errno();
106}
107
108static void ct_dump_dir(struct nfnl_ct *ct, int repl,
109 struct nl_dump_params *p)
110{
111 struct nl_addr *addr;
112 char addrbuf[64];
113
114 addr = nfnl_ct_get_src(ct, repl);
115 if (addr)
116 dp_dump(p, "src=%s ",
117 nl_addr2str(addr, addrbuf, sizeof(addrbuf)));
118
119 addr = nfnl_ct_get_dst(ct, repl);
120 if (addr)
121 dp_dump(p, "dst=%s ",
122 nl_addr2str(addr, addrbuf, sizeof(addrbuf)));
123
124 if (nfnl_ct_test_src_port(ct, repl))
125 dp_dump(p, "sport=%u ", ntohs(nfnl_ct_get_src_port(ct, repl)));
126 if (nfnl_ct_test_dst_port(ct, repl))
127 dp_dump(p, "dport=%u ", ntohs(nfnl_ct_get_dst_port(ct, repl)));
128
129 if (nfnl_ct_test_icmp_type(ct, repl))
130 dp_dump(p, "type=%d ", nfnl_ct_get_icmp_type(ct, repl));
131 if (nfnl_ct_test_icmp_type(ct, repl))
132 dp_dump(p, "code=%d ", nfnl_ct_get_icmp_code(ct, repl));
133 if (nfnl_ct_test_icmp_type(ct, repl))
134 dp_dump(p, "id=%d ", ntohs(nfnl_ct_get_icmp_id(ct, repl)));
135
136 if (nfnl_ct_test_packets(ct, repl))
137 dp_dump(p, "packets=%llu ", nfnl_ct_get_packets(ct, repl));
138 if (nfnl_ct_test_bytes(ct, repl))
139 dp_dump(p, "bytes=%llu ", nfnl_ct_get_bytes(ct, repl));
140}
141
142/* Compatible with /proc/net/nf_conntrack */
143static int ct_dump(struct nl_object *a, struct nl_dump_params *p)
144{
145 struct nfnl_ct *ct = (struct nfnl_ct *) a;
146 char buf[64];
147 uint32_t status;
148 uint8_t family;
149 uint8_t proto;
150
151 family = nfnl_ct_get_family(ct);
152 dp_dump(p, "%-8s %u ", nl_af2str(family, buf, sizeof(buf)), family);
153
154 if (nfnl_ct_test_proto(ct)) {
155 proto = nfnl_ct_get_proto(ct);
156 dp_dump(p, "%-8s %u ",
157 nl_ip_proto2str(proto, buf, sizeof(buf)), proto);
158 }
159
160 if (nfnl_ct_test_timeout(ct))
161 dp_dump(p, "%ld ", nfnl_ct_get_timeout(ct));
162
163 if (nfnl_ct_test_tcp_state(ct))
164 dp_dump(p, "%s ",
165 nfnl_ct_tcp_state2str(nfnl_ct_get_tcp_state(ct),
166 buf, sizeof(buf)));
167
168 ct_dump_dir(ct, 0, p);
169
170 status = nfnl_ct_get_status(ct);
171 if (!(status & IPS_SEEN_REPLY))
172 dp_dump(p, "[UNREPLIED] ");
173
174 ct_dump_dir(ct, 1, p);
175
176 if (status & IPS_ASSURED)
177 dp_dump(p, "[ASSURED] ");
178
179 if (nfnl_ct_test_mark(ct))
180 dp_dump(p, "mark=%u ", nfnl_ct_get_mark(ct));
181
182 if (nfnl_ct_test_use(ct))
183 dp_dump(p, "use=%u ", nfnl_ct_get_use(ct));
184
185 dp_dump(p, "\n");
186
187 return 1;
188}
189
190static int ct_compare(struct nl_object *_a, struct nl_object *_b,
191 uint32_t attrs, int flags)
192{
193 struct nfnl_ct *a = (struct nfnl_ct *) _a;
194 struct nfnl_ct *b = (struct nfnl_ct *) _b;
195 int diff = 0;
196
197#define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR)
198#define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD)
199#define CT_DIFF_ADDR(ATTR, FIELD) \
200 ((flags & LOOSE_FLAG_COMPARISON) \
201 ? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \
202 : CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
203
204 diff |= CT_DIFF_VAL(FAMILY, ct_family);
205 diff |= CT_DIFF_VAL(PROTO, ct_proto);
206 diff |= CT_DIFF_VAL(TCP_STATE, ct_protoinfo.tcp.state);
207 diff |= CT_DIFF_VAL(TIMEOUT, ct_timeout);
208 diff |= CT_DIFF_VAL(MARK, ct_mark);
209 diff |= CT_DIFF_VAL(USE, ct_use);
210 diff |= CT_DIFF_VAL(ID, ct_id);
211 diff |= CT_DIFF_ADDR(ORIG_SRC, ct_orig.src);
212 diff |= CT_DIFF_ADDR(ORIG_DST, ct_orig.dst);
213 diff |= CT_DIFF_VAL(ORIG_SRC_PORT, ct_orig.proto.port.src);
214 diff |= CT_DIFF_VAL(ORIG_DST_PORT, ct_orig.proto.port.dst);
215 diff |= CT_DIFF_VAL(ORIG_ICMP_ID, ct_orig.proto.icmp.id);
216 diff |= CT_DIFF_VAL(ORIG_ICMP_TYPE, ct_orig.proto.icmp.type);
217 diff |= CT_DIFF_VAL(ORIG_ICMP_CODE, ct_orig.proto.icmp.code);
218 diff |= CT_DIFF_VAL(ORIG_PACKETS, ct_orig.packets);
219 diff |= CT_DIFF_VAL(ORIG_BYTES, ct_orig.bytes);
220 diff |= CT_DIFF_ADDR(REPL_SRC, ct_repl.src);
221 diff |= CT_DIFF_ADDR(REPL_DST, ct_repl.dst);
222 diff |= CT_DIFF_VAL(REPL_SRC_PORT, ct_repl.proto.port.src);
223 diff |= CT_DIFF_VAL(REPL_DST_PORT, ct_repl.proto.port.dst);
224 diff |= CT_DIFF_VAL(REPL_ICMP_ID, ct_repl.proto.icmp.id);
225 diff |= CT_DIFF_VAL(REPL_ICMP_TYPE, ct_repl.proto.icmp.type);
226 diff |= CT_DIFF_VAL(REPL_ICMP_CODE, ct_repl.proto.icmp.code);
227 diff |= CT_DIFF_VAL(REPL_PACKETS, ct_repl.packets);
228 diff |= CT_DIFF_VAL(REPL_BYTES, ct_repl.bytes);
229
230 if (flags & LOOSE_FLAG_COMPARISON)
231 diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) &
232 b->ct_status_mask);
233 else
234 diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status);
235
236#undef CT_DIFF
237#undef CT_DIFF_VAL
238#undef CT_DIFF_ADDR
239
240 return diff;
241}
242
243static struct trans_tbl ct_attrs[] = {
244 __ADD(CT_ATTR_FAMILY, family)
245 __ADD(CT_ATTR_PROTO, proto)
246 __ADD(CT_ATTR_TCP_STATE, tcpstate)
247 __ADD(CT_ATTR_STATUS, status)
248 __ADD(CT_ATTR_TIMEOUT, timeout)
249 __ADD(CT_ATTR_MARK, mark)
250 __ADD(CT_ATTR_USE, use)
251 __ADD(CT_ATTR_ID, id)
252 __ADD(CT_ATTR_ORIG_SRC, origsrc)
253 __ADD(CT_ATTR_ORIG_DST, origdst)
254 __ADD(CT_ATTR_ORIG_SRC_PORT, origsrcport)
255 __ADD(CT_ATTR_ORIG_DST_PORT, origdstport)
256 __ADD(CT_ATTR_ORIG_ICMP_ID, origicmpid)
257 __ADD(CT_ATTR_ORIG_ICMP_TYPE, origicmptype)
258 __ADD(CT_ATTR_ORIG_ICMP_CODE, origicmpcode)
259 __ADD(CT_ATTR_ORIG_PACKETS, origpackets)
260 __ADD(CT_ATTR_ORIG_BYTES, origbytes)
261 __ADD(CT_ATTR_REPL_SRC, replysrc)
262 __ADD(CT_ATTR_REPL_DST, replydst)
263 __ADD(CT_ATTR_REPL_SRC_PORT, replysrcport)
264 __ADD(CT_ATTR_REPL_DST_PORT, replydstport)
265 __ADD(CT_ATTR_REPL_ICMP_ID, replyicmpid)
266 __ADD(CT_ATTR_REPL_ICMP_TYPE, replyicmptype)
267 __ADD(CT_ATTR_REPL_ICMP_CODE, replyicmpcode)
268 __ADD(CT_ATTR_REPL_PACKETS, replypackets)
269 __ADD(CT_ATTR_REPL_BYTES, replybytes)
270};
271
272static char *ct_attrs2str(int attrs, char *buf, size_t len)
273{
274 return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs));
275}
276
277/**
278 * @name Allocation/Freeing
279 * @{
280 */
281
282struct nfnl_ct *nfnl_ct_alloc(void)
283{
284 return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops);
285}
286
287void nfnl_ct_get(struct nfnl_ct *ct)
288{
289 nl_object_get((struct nl_object *) ct);
290}
291
292void nfnl_ct_put(struct nfnl_ct *ct)
293{
294 nl_object_put((struct nl_object *) ct);
295}
296
297/** @} */
298
299/**
300 * @name Attributes
301 * @{
302 */
303
304void nfnl_ct_set_family(struct nfnl_ct *ct, uint8_t family)
305{
306 ct->ct_family = family;
307 ct->ce_mask |= CT_ATTR_FAMILY;
308}
309
310uint8_t nfnl_ct_get_family(const struct nfnl_ct *ct)
311{
312 if (ct->ce_mask & CT_ATTR_FAMILY)
313 return ct->ct_family;
314 else
315 return AF_UNSPEC;
316}
317
318void nfnl_ct_set_proto(struct nfnl_ct *ct, uint8_t proto)
319{
320 ct->ct_proto = proto;
321 ct->ce_mask |= CT_ATTR_PROTO;
322}
323
324int nfnl_ct_test_proto(const struct nfnl_ct *ct)
325{
326 return !!(ct->ce_mask & CT_ATTR_PROTO);
327}
328
329uint8_t nfnl_ct_get_proto(const struct nfnl_ct *ct)
330{
331 return ct->ct_proto;
332}
333
334void nfnl_ct_set_tcp_state(struct nfnl_ct *ct, uint8_t state)
335{
336 ct->ct_protoinfo.tcp.state = state;
337 ct->ce_mask |= CT_ATTR_TCP_STATE;
338}
339
340int nfnl_ct_test_tcp_state(const struct nfnl_ct *ct)
341{
342 return !!(ct->ce_mask & CT_ATTR_TCP_STATE);
343}
344
345uint8_t nfnl_ct_get_tcp_state(const struct nfnl_ct *ct)
346{
347 return ct->ct_protoinfo.tcp.state;
348}
349
350static struct trans_tbl tcp_states[] = {
351 __ADD(TCP_CONNTRACK_NONE,NONE)
352 __ADD(TCP_CONNTRACK_SYN_SENT,SYN_SENT)
353 __ADD(TCP_CONNTRACK_SYN_RECV,SYN_RECV)
354 __ADD(TCP_CONNTRACK_ESTABLISHED,ESTABLISHED)
355 __ADD(TCP_CONNTRACK_FIN_WAIT,FIN_WAIT)
356 __ADD(TCP_CONNTRACK_CLOSE_WAIT,CLOSE_WAIT)
357 __ADD(TCP_CONNTRACK_LAST_ACK,LAST_ACK)
358 __ADD(TCP_CONNTRACK_TIME_WAIT,TIME_WAIT)
359 __ADD(TCP_CONNTRACK_CLOSE,CLOSE)
360 __ADD(TCP_CONNTRACK_LISTEN,LISTEN)
361};
362
363char *nfnl_ct_tcp_state2str(uint8_t state, char *buf, size_t len)
364{
365 return __type2str(state, buf, len, tcp_states, ARRAY_SIZE(tcp_states));
366}
367
368int nfnl_ct_str2tcp_state(const char *name)
369{
370 return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states));
371}
372
373void nfnl_ct_set_status(struct nfnl_ct *ct, uint32_t status)
374{
375 ct->ct_status_mask |= status;
376 ct->ct_status |= status;
377 ct->ce_mask |= CT_ATTR_STATUS;
378}
379
380void nfnl_ct_unset_status(struct nfnl_ct *ct, uint32_t status)
381{
382 ct->ct_status_mask |= status;
383 ct->ct_status &= ~status;
384 ct->ce_mask |= CT_ATTR_STATUS;
385}
386
387uint32_t nfnl_ct_get_status(const struct nfnl_ct *ct)
388{
389 return ct->ct_status;
390}
391
392void nfnl_ct_set_timeout(struct nfnl_ct *ct, uint32_t timeout)
393{
394 ct->ct_timeout = timeout;
395 ct->ce_mask |= CT_ATTR_TIMEOUT;
396}
397
398int nfnl_ct_test_timeout(const struct nfnl_ct *ct)
399{
400 return !!(ct->ce_mask & CT_ATTR_TIMEOUT);
401}
402
403uint32_t nfnl_ct_get_timeout(const struct nfnl_ct *ct)
404{
405 return ct->ct_timeout;
406}
407
408void nfnl_ct_set_mark(struct nfnl_ct *ct, uint32_t mark)
409{
410 ct->ct_mark = mark;
411 ct->ce_mask |= CT_ATTR_MARK;
412}
413
414int nfnl_ct_test_mark(const struct nfnl_ct *ct)
415{
416 return !!(ct->ce_mask & CT_ATTR_MARK);
417}
418
419uint32_t nfnl_ct_get_mark(const struct nfnl_ct *ct)
420{
421 return ct->ct_mark;
422}
423
424void nfnl_ct_set_use(struct nfnl_ct *ct, uint32_t use)
425{
426 ct->ct_use = use;
427 ct->ce_mask |= CT_ATTR_USE;
428}
429
430int nfnl_ct_test_use(const struct nfnl_ct *ct)
431{
432 return !!(ct->ce_mask & CT_ATTR_USE);
433}
434
435uint32_t nfnl_ct_get_use(const struct nfnl_ct *ct)
436{
437 return ct->ct_use;
438}
439
440void nfnl_ct_set_id(struct nfnl_ct *ct, uint32_t id)
441{
442 ct->ct_id = id;
443 ct->ce_mask |= CT_ATTR_ID;
444}
445
446int nfnl_ct_test_id(const struct nfnl_ct *ct)
447{
448 return !!(ct->ce_mask & CT_ATTR_ID);
449}
450
451uint32_t nfnl_ct_get_id(const struct nfnl_ct *ct)
452{
453 return ct->ct_id;
454}
455
456static int ct_set_addr(struct nfnl_ct *ct, struct nl_addr *addr,
457 int attr, struct nl_addr ** ct_addr)
458{
459 if (ct->ce_mask & CT_ATTR_FAMILY) {
460 if (addr->a_family != ct->ct_family)
461 return nl_error(EINVAL, "Address family mismatch");
462 } else
463 nfnl_ct_set_family(ct, addr->a_family);
464
465 if (*ct_addr)
466 nl_addr_put(*ct_addr);
467
468 nl_addr_get(addr);
469 *ct_addr = addr;
470 ct->ce_mask |= attr;
471
472 return 0;
473}
474
475int nfnl_ct_set_src(struct nfnl_ct *ct, int repl, struct nl_addr *addr)
476{
477 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
478 int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
479 return ct_set_addr(ct, addr, attr, &dir->src);
480}
481
482int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr)
483{
484 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
485 int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
486 return ct_set_addr(ct, addr, attr, &dir->dst);
487}
488
489struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl)
490{
491 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
492 int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
493 if (!(ct->ce_mask & attr))
494 return NULL;
495 return dir->src;
496}
497
498struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl)
499{
500 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
501 int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
502 if (!(ct->ce_mask & attr))
503 return NULL;
504 return dir->dst;
505}
506
507void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port)
508{
509 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
510 int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
511
512 dir->proto.port.src = port;
513 ct->ce_mask |= attr;
514}
515
516int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl)
517{
518 int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
519 return !!(ct->ce_mask & attr);
520}
521
522uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl)
523{
524 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
525
526 return dir->proto.port.src;
527}
528
529void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port)
530{
531 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
532 int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
533
534 dir->proto.port.dst = port;
535 ct->ce_mask |= attr;
536}
537
538int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl)
539{
540 int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
541 return !!(ct->ce_mask & attr);
542}
543
544uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl)
545{
546 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
547
548 return dir->proto.port.dst;
549}
550
551void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id)
552{
553 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
554 int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
555
556 dir->proto.icmp.id = id;
557 ct->ce_mask |= attr;
558}
559
560int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl)
561{
562 int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
563 return !!(ct->ce_mask & attr);
564}
565
566uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl)
567{
568 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
569
570 return dir->proto.icmp.id;
571}
572
573void nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type)
574{
575 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
576 int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
577
578 dir->proto.icmp.type = type;
579 ct->ce_mask |= attr;
580}
581
582int nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl)
583{
584 int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
585 return !!(ct->ce_mask & attr);
586}
587
588uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl)
589{
590 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
591
592 return dir->proto.icmp.type;
593}
594
595void nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code)
596{
597 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
598 int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
599
600 dir->proto.icmp.code = code;
601 ct->ce_mask |= attr;
602}
603
604int nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl)
605{
606 int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
607 return !!(ct->ce_mask & attr);
608}
609
610uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int repl)
611{
612 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
613
614 return dir->proto.icmp.code;
615}
616
617void nfnl_ct_set_packets(struct nfnl_ct *ct, int repl, uint64_t packets)
618{
619 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
620 int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS;
621
622 dir->packets = packets;
623 ct->ce_mask |= attr;
624}
625
626int nfnl_ct_test_packets(const struct nfnl_ct *ct, int repl)
627{
628 int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS;
629 return !!(ct->ce_mask & attr);
630}
631
632uint64_t nfnl_ct_get_packets(const struct nfnl_ct *ct, int repl)
633{
634 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
635
636 return dir->packets;
637}
638
639void nfnl_ct_set_bytes(struct nfnl_ct *ct, int repl, uint64_t bytes)
640{
641 struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
642 int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES;
643
644 dir->bytes = bytes;
645 ct->ce_mask |= attr;
646}
647
648int nfnl_ct_test_bytes(const struct nfnl_ct *ct, int repl)
649{
650 int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES;
651 return !!(ct->ce_mask & attr);
652}
653
654uint64_t nfnl_ct_get_bytes(const struct nfnl_ct *ct, int repl)
655{
656 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
657
658 return dir->bytes;
659}
660
661/** @} */
662
663struct nl_object_ops ct_obj_ops = {
664 .oo_name = "netfilter/ct",
665 .oo_size = sizeof(struct nfnl_ct),
666 .oo_free_data = ct_free_data,
667 .oo_clone = ct_clone,
668 .oo_dump[NL_DUMP_BRIEF] = ct_dump,
669 .oo_dump[NL_DUMP_FULL] = ct_dump,
670 .oo_dump[NL_DUMP_STATS] = ct_dump,
671 .oo_compare = ct_compare,
672 .oo_attrs2str = ct_attrs2str,
673};
674
675/** @} */
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:802
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:406
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:178
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:167
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition: object.c:42
@ NL_DUMP_FULL
Dump all attributes but no statistics.
Definition: types.h:23
@ NL_DUMP_BRIEF
Dump object in a brief one-liner.
Definition: types.h:22
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition: types.h:24
Dumping parameters.
Definition: types.h:37
Object Operations.
Definition: object-api.h:255
char * oo_name
Unique name of object type.
Definition: object-api.h:261