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>
19 #include <netlink-local.h>
20 #include <netlink/netfilter/nfnl.h>
21 #include <netlink/netfilter/ct.h>
24 #define CT_ATTR_FAMILY (1UL << 0)
25 #define CT_ATTR_PROTO (1UL << 1)
27 #define CT_ATTR_TCP_STATE (1UL << 2)
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)
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)
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)
56 static void ct_free_data(
struct nl_object *c)
58 struct nfnl_ct *ct = (
struct nfnl_ct *) c;
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);
69 static int ct_clone(
struct nl_object *_dst,
struct nl_object *_src)
71 struct nfnl_ct *dst = (
struct nfnl_ct *) _dst;
72 struct nfnl_ct *src = (
struct nfnl_ct *) _src;
75 if (src->ct_orig.src) {
79 dst->ct_orig.src = addr;
82 if (src->ct_orig.dst) {
86 dst->ct_orig.dst = addr;
89 if (src->ct_repl.src) {
93 dst->ct_repl.src = addr;
96 if (src->ct_repl.dst) {
100 dst->ct_repl.dst = addr;
105 return nl_get_errno();
108 static void ct_dump_dir(
struct nfnl_ct *ct,
int repl,
111 struct nl_addr *addr;
114 addr = nfnl_ct_get_src(ct, repl);
116 dp_dump(p,
"src=%s ",
119 addr = nfnl_ct_get_dst(ct, repl);
121 dp_dump(p,
"dst=%s ",
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)));
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)));
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));
145 struct nfnl_ct *ct = (
struct nfnl_ct *) a;
151 family = nfnl_ct_get_family(ct);
152 dp_dump(p,
"%-8s %u ", nl_af2str(family, buf,
sizeof(buf)), family);
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);
160 if (nfnl_ct_test_timeout(ct))
161 dp_dump(p,
"%ld ", nfnl_ct_get_timeout(ct));
163 if (nfnl_ct_test_tcp_state(ct))
165 nfnl_ct_tcp_state2str(nfnl_ct_get_tcp_state(ct),
168 ct_dump_dir(ct, 0, p);
170 status = nfnl_ct_get_status(ct);
171 if (!(status & IPS_SEEN_REPLY))
172 dp_dump(p,
"[UNREPLIED] ");
174 ct_dump_dir(ct, 1, p);
176 if (status & IPS_ASSURED)
177 dp_dump(p,
"[ASSURED] ");
179 if (nfnl_ct_test_mark(ct))
180 dp_dump(p,
"mark=%u ", nfnl_ct_get_mark(ct));
182 if (nfnl_ct_test_use(ct))
183 dp_dump(p,
"use=%u ", nfnl_ct_get_use(ct));
190 static int ct_compare(
struct nl_object *_a,
struct nl_object *_b,
191 uint32_t attrs,
int flags)
193 struct nfnl_ct *a = (
struct nfnl_ct *) _a;
194 struct nfnl_ct *b = (
struct nfnl_ct *) _b;
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)))
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);
230 if (flags & LOOSE_FLAG_COMPARISON)
231 diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) &
234 diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status);
243 static 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)
272 static
char *ct_attrs2str(
int attrs,
char *buf,
size_t len)
274 return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs));
282 struct nfnl_ct *nfnl_ct_alloc(
void)
287 void nfnl_ct_get(
struct nfnl_ct *ct)
292 void nfnl_ct_put(
struct nfnl_ct *ct)
304 void nfnl_ct_set_family(
struct nfnl_ct *ct, uint8_t family)
306 ct->ct_family = family;
307 ct->ce_mask |= CT_ATTR_FAMILY;
310 uint8_t nfnl_ct_get_family(
const struct nfnl_ct *ct)
312 if (ct->ce_mask & CT_ATTR_FAMILY)
313 return ct->ct_family;
318 void nfnl_ct_set_proto(
struct nfnl_ct *ct, uint8_t proto)
320 ct->ct_proto = proto;
321 ct->ce_mask |= CT_ATTR_PROTO;
324 int nfnl_ct_test_proto(
const struct nfnl_ct *ct)
326 return !!(ct->ce_mask & CT_ATTR_PROTO);
329 uint8_t nfnl_ct_get_proto(
const struct nfnl_ct *ct)
334 void nfnl_ct_set_tcp_state(
struct nfnl_ct *ct, uint8_t state)
336 ct->ct_protoinfo.tcp.state = state;
337 ct->ce_mask |= CT_ATTR_TCP_STATE;
340 int nfnl_ct_test_tcp_state(
const struct nfnl_ct *ct)
342 return !!(ct->ce_mask & CT_ATTR_TCP_STATE);
345 uint8_t nfnl_ct_get_tcp_state(
const struct nfnl_ct *ct)
347 return ct->ct_protoinfo.tcp.state;
350 static 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)
363 char *nfnl_ct_tcp_state2str(uint8_t state,
char *buf,
size_t len)
365 return __type2str(state, buf, len, tcp_states, ARRAY_SIZE(tcp_states));
368 int nfnl_ct_str2tcp_state(
const char *name)
370 return __str2type(name, tcp_states, ARRAY_SIZE(tcp_states));
373 void nfnl_ct_set_status(
struct nfnl_ct *ct, uint32_t status)
375 ct->ct_status_mask |= status;
376 ct->ct_status |= status;
377 ct->ce_mask |= CT_ATTR_STATUS;
380 void nfnl_ct_unset_status(
struct nfnl_ct *ct, uint32_t status)
382 ct->ct_status_mask |= status;
383 ct->ct_status &= ~status;
384 ct->ce_mask |= CT_ATTR_STATUS;
387 uint32_t nfnl_ct_get_status(
const struct nfnl_ct *ct)
389 return ct->ct_status;
392 void nfnl_ct_set_timeout(
struct nfnl_ct *ct, uint32_t timeout)
394 ct->ct_timeout = timeout;
395 ct->ce_mask |= CT_ATTR_TIMEOUT;
398 int nfnl_ct_test_timeout(
const struct nfnl_ct *ct)
400 return !!(ct->ce_mask & CT_ATTR_TIMEOUT);
403 uint32_t nfnl_ct_get_timeout(
const struct nfnl_ct *ct)
405 return ct->ct_timeout;
408 void nfnl_ct_set_mark(
struct nfnl_ct *ct, uint32_t mark)
411 ct->ce_mask |= CT_ATTR_MARK;
414 int nfnl_ct_test_mark(
const struct nfnl_ct *ct)
416 return !!(ct->ce_mask & CT_ATTR_MARK);
419 uint32_t nfnl_ct_get_mark(
const struct nfnl_ct *ct)
424 void nfnl_ct_set_use(
struct nfnl_ct *ct, uint32_t use)
427 ct->ce_mask |= CT_ATTR_USE;
430 int nfnl_ct_test_use(
const struct nfnl_ct *ct)
432 return !!(ct->ce_mask & CT_ATTR_USE);
435 uint32_t nfnl_ct_get_use(
const struct nfnl_ct *ct)
440 void nfnl_ct_set_id(
struct nfnl_ct *ct, uint32_t
id)
443 ct->ce_mask |= CT_ATTR_ID;
446 int nfnl_ct_test_id(
const struct nfnl_ct *ct)
448 return !!(ct->ce_mask & CT_ATTR_ID);
451 uint32_t nfnl_ct_get_id(
const struct nfnl_ct *ct)
456 static int ct_set_addr(
struct nfnl_ct *ct,
struct nl_addr *addr,
457 int attr,
struct nl_addr ** ct_addr)
459 if (ct->ce_mask & CT_ATTR_FAMILY) {
460 if (addr->a_family != ct->ct_family)
461 return nl_error(EINVAL,
"Address family mismatch");
463 nfnl_ct_set_family(ct, addr->a_family);
466 nl_addr_put(*ct_addr);
475 int nfnl_ct_set_src(
struct nfnl_ct *ct,
int repl,
struct nl_addr *addr)
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);
482 int nfnl_ct_set_dst(
struct nfnl_ct *ct,
int repl,
struct nl_addr *addr)
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);
489 struct nl_addr *nfnl_ct_get_src(
const struct nfnl_ct *ct,
int repl)
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))
498 struct nl_addr *nfnl_ct_get_dst(
const struct nfnl_ct *ct,
int repl)
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))
507 void nfnl_ct_set_src_port(
struct nfnl_ct *ct,
int repl, uint16_t port)
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;
512 dir->proto.port.src = port;
516 int nfnl_ct_test_src_port(
const struct nfnl_ct *ct,
int repl)
518 int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
519 return !!(ct->ce_mask & attr);
522 uint16_t nfnl_ct_get_src_port(
const struct nfnl_ct *ct,
int repl)
524 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
526 return dir->proto.port.src;
529 void nfnl_ct_set_dst_port(
struct nfnl_ct *ct,
int repl, uint16_t port)
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;
534 dir->proto.port.dst = port;
538 int nfnl_ct_test_dst_port(
const struct nfnl_ct *ct,
int repl)
540 int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
541 return !!(ct->ce_mask & attr);
544 uint16_t nfnl_ct_get_dst_port(
const struct nfnl_ct *ct,
int repl)
546 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
548 return dir->proto.port.dst;
551 void nfnl_ct_set_icmp_id(
struct nfnl_ct *ct,
int repl, uint16_t
id)
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;
556 dir->proto.icmp.id = id;
560 int nfnl_ct_test_icmp_id(
const struct nfnl_ct *ct,
int repl)
562 int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
563 return !!(ct->ce_mask & attr);
566 uint16_t nfnl_ct_get_icmp_id(
const struct nfnl_ct *ct,
int repl)
568 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
570 return dir->proto.icmp.id;
573 void nfnl_ct_set_icmp_type(
struct nfnl_ct *ct,
int repl, uint8_t type)
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;
578 dir->proto.icmp.type = type;
582 int nfnl_ct_test_icmp_type(
const struct nfnl_ct *ct,
int repl)
584 int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
585 return !!(ct->ce_mask & attr);
588 uint8_t nfnl_ct_get_icmp_type(
const struct nfnl_ct *ct,
int repl)
590 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
592 return dir->proto.icmp.type;
595 void nfnl_ct_set_icmp_code(
struct nfnl_ct *ct,
int repl, uint8_t code)
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;
600 dir->proto.icmp.code = code;
604 int nfnl_ct_test_icmp_code(
const struct nfnl_ct *ct,
int repl)
606 int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
607 return !!(ct->ce_mask & attr);
610 uint8_t nfnl_ct_get_icmp_code(
const struct nfnl_ct *ct,
int repl)
612 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
614 return dir->proto.icmp.code;
617 void nfnl_ct_set_packets(
struct nfnl_ct *ct,
int repl, uint64_t packets)
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;
622 dir->packets = packets;
626 int nfnl_ct_test_packets(
const struct nfnl_ct *ct,
int repl)
628 int attr = repl ? CT_ATTR_REPL_PACKETS : CT_ATTR_ORIG_PACKETS;
629 return !!(ct->ce_mask & attr);
632 uint64_t nfnl_ct_get_packets(
const struct nfnl_ct *ct,
int repl)
634 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
639 void nfnl_ct_set_bytes(
struct nfnl_ct *ct,
int repl, uint64_t bytes)
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;
648 int nfnl_ct_test_bytes(
const struct nfnl_ct *ct,
int repl)
650 int attr = repl ? CT_ATTR_REPL_BYTES : CT_ATTR_ORIG_BYTES;
651 return !!(ct->ce_mask & attr);
654 uint64_t nfnl_ct_get_bytes(
const struct nfnl_ct *ct,
int repl)
656 const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
665 .oo_size =
sizeof(
struct nfnl_ct),
666 .oo_free_data = ct_free_data,
667 .oo_clone = ct_clone,
671 .oo_compare = ct_compare,
672 .oo_attrs2str = ct_attrs2str,
Dump object in a brief one-liner.
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
char * oo_name
Unique name of object type.
Dump all attributes but no statistics.
Dump all attributes including statistics.