10#include "internal/internal.h"
12static int __snprintf_l3protocol(
char *buf,
14 const struct nf_conntrack *ct)
16 uint8_t num = ct->head.orig.l3protonum;
18 if (!test_bit(ATTR_ORIG_L3PROTO, ct->head.set))
21 return snprintf(buf, len,
"%-8s %u ", __l3proto2str(num), num);
24int __snprintf_protocol(
char *buf,
26 const struct nf_conntrack *ct)
28 uint8_t num = ct->head.orig.protonum;
30 if (!test_bit(ATTR_ORIG_L4PROTO, ct->head.set))
33 return snprintf(buf, len,
"%-8s %u ", __proto2str(num), num);
36static int __snprintf_timeout(
char *buf,
38 const struct nf_conntrack *ct)
40 return snprintf(buf, len,
"%u ", ct->timeout);
43static int __snprintf_protoinfo(
char *buf,
45 const struct nf_conntrack *ct)
47 uint8_t state = ct->protoinfo.tcp.state;
48 const char *str = NULL;
50 if (state < ARRAY_SIZE(states))
54 str = states[TCP_CONNTRACK_NONE];
56 return snprintf(buf, len,
"%s ", str);
59static int __snprintf_protoinfo_sctp(
char *buf,
61 const struct nf_conntrack *ct)
63 uint8_t state = ct->protoinfo.sctp.state;
64 const char *str = NULL;
66 if (state < ARRAY_SIZE(sctp_states))
67 str = sctp_states[state];
70 str = sctp_states[SCTP_CONNTRACK_NONE];
72 return snprintf(buf, len,
"%s ", str);
75static int __snprintf_protoinfo_dccp(
char *buf,
77 const struct nf_conntrack *ct)
79 const char *str = NULL;
80 uint8_t state = ct->protoinfo.dccp.state;
82 if (state < ARRAY_SIZE(dccp_states))
83 str = dccp_states[state];
86 str = dccp_states[DCCP_CONNTRACK_NONE];
88 return snprintf(buf, len,
"%s ", str);
91static int __snprintf_address_ipv4(
char *buf,
93 const struct __nfct_tuple *tuple,
97 int ret, size = 0, offset = 0;
98 struct in_addr src = { .s_addr = tuple->src.v4 };
99 struct in_addr dst = { .s_addr = tuple->dst.v4 };
101 ret = snprintf(buf, len,
"%s=%s ", src_tag, inet_ntoa(src));
102 BUFFER_SIZE(ret, size, len, offset);
104 ret = snprintf(buf+offset, len,
"%s=%s ", dst_tag, inet_ntoa(dst));
105 BUFFER_SIZE(ret, size, len, offset);
110static int __snprintf_address_ipv6(
char *buf,
112 const struct __nfct_tuple *tuple,
116 int ret, size = 0, offset = 0;
119 char tmp[INET6_ADDRSTRLEN];
121 memcpy(&src, &tuple->src.v6,
sizeof(
struct in6_addr));
122 memcpy(&dst, &tuple->dst.v6,
sizeof(
struct in6_addr));
124 if (!inet_ntop(AF_INET6, &src, tmp,
sizeof(tmp)))
127 ret = snprintf(buf, len,
"%s=%s ", src_tag, tmp);
128 BUFFER_SIZE(ret, size, len, offset);
130 if (!inet_ntop(AF_INET6, &dst, tmp,
sizeof(tmp)))
133 ret = snprintf(buf + offset, len,
"%s=%s ", dst_tag, tmp);
134 BUFFER_SIZE(ret, size, len, offset);
139int __snprintf_address(
char *buf,
141 const struct __nfct_tuple *tuple,
147 switch (tuple->l3protonum) {
149 size = __snprintf_address_ipv4(buf, len, tuple,
153 size = __snprintf_address_ipv6(buf, len, tuple,
161int __snprintf_proto(
char *buf,
163 const struct __nfct_tuple *tuple)
167 switch(tuple->protonum) {
170 case IPPROTO_UDPLITE:
173 return snprintf(buf, len,
"sport=%u dport=%u ",
174 ntohs(tuple->l4src.tcp.port),
175 ntohs(tuple->l4dst.tcp.port));
178 return snprintf(buf, len,
"srckey=0x%x dstkey=0x%x ",
179 ntohs(tuple->l4src.all),
180 ntohs(tuple->l4dst.all));
186 return (snprintf(buf, len,
"type=%d code=%d id=%d ",
187 tuple->l4dst.icmp.type,
188 tuple->l4dst.icmp.code,
189 ntohs(tuple->l4src.icmp.id)));
197__snprintf_tuple_zone(
char *buf,
unsigned int len,
const char *pfx,
198 const struct __nfct_tuple *tuple)
200 return (snprintf(buf, len,
"zone-%s=%u ", pfx, tuple->zone));
203static int __snprintf_status_assured(
char *buf,
205 const struct nf_conntrack *ct)
209 if (ct->status & IPS_HW_OFFLOAD)
210 size = snprintf(buf, len,
"[HW_OFFLOAD] ");
211 else if (ct->status & IPS_OFFLOAD)
212 size = snprintf(buf, len,
"[OFFLOAD] ");
213 else if (ct->status & IPS_ASSURED)
214 size = snprintf(buf, len,
"[ASSURED] ");
219static int __snprintf_status_not_seen_reply(
char *buf,
221 const struct nf_conntrack *ct)
225 if (!(ct->status & IPS_SEEN_REPLY))
226 size = snprintf(buf, len,
"[UNREPLIED] ");
231static int __snprintf_counters(
char *buf,
233 const struct nf_conntrack *ct,
236 return (snprintf(buf, len,
"packets=%llu bytes=%llu ",
237 (
unsigned long long) ct->counters[dir].packets,
238 (
unsigned long long) ct->counters[dir].bytes));
242__snprintf_mark(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
244 return (snprintf(buf, len,
"mark=%u ", ct->mark));
248__snprintf_secmark(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
250 return (snprintf(buf, len,
"secmark=%u ", ct->secmark));
254__snprintf_use(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
256 return (snprintf(buf, len,
"use=%u ", ct->use));
260__snprintf_id(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
262 return (snprintf(buf, len,
"id=%u ", ct->id));
266__snprintf_zone(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
268 return (snprintf(buf, len,
"zone=%u ", ct->zone));
272__snprintf_secctx(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
274 return (snprintf(buf, len,
"secctx=%s ", ct->secctx));
278__snprintf_timestamp_start(
char *buf,
unsigned int len,
279 const struct nf_conntrack *ct)
281 time_t start = (time_t)(ct->timestamp.start / NSEC_PER_SEC);
282 char *tmp = ctime(&start);
285 tmp[strlen(tmp)-1] =
'\0';
286 return (snprintf(buf, len,
"[start=%s] ", tmp));
290__snprintf_timestamp_stop(
char *buf,
unsigned int len,
291 const struct nf_conntrack *ct)
293 time_t stop = (time_t)(ct->timestamp.stop / NSEC_PER_SEC);
294 char *tmp = ctime(&stop);
297 tmp[strlen(tmp)-1] =
'\0';
298 return (snprintf(buf, len,
"[stop=%s] ", tmp));
302__snprintf_timestamp_delta(
char *buf,
unsigned int len,
303 const struct nf_conntrack *ct)
305 time_t delta_time, stop;
307 if (ct->timestamp.stop == 0)
310 stop = (time_t)(ct->timestamp.stop / NSEC_PER_SEC);
312 delta_time = stop - (time_t)(ct->timestamp.start / NSEC_PER_SEC);
314 return (snprintf(buf, len,
"delta-time=%llu ",
315 (
unsigned long long)delta_time));
319__snprintf_helper_name(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
321 return (snprintf(buf, len,
"helper=%s ", ct->helper_name));
325__snprintf_connlabels(
char *buf,
unsigned int len,
327 const struct nfct_bitmask *b,
const char *fmt)
330 int ret, size = 0, offset = 0;
332 max = nfct_bitmask_maxbit(b);
333 for (i = 0; i <= max && len; i++) {
335 if (!nfct_bitmask_test_bit(b, i))
338 if (!name || strcmp(name,
"") == 0)
341 ret = snprintf(buf + offset, len, fmt, name);
342 BUFFER_SIZE(ret, size, len, offset);
348__snprintf_clabels(
char *buf,
unsigned int len,
351 const struct nfct_bitmask *b =
nfct_get_attr(ct, ATTR_CONNLABELS);
352 int ret, size = 0, offset = 0;
357 ret = snprintf(buf, len,
"labels=");
358 BUFFER_SIZE(ret, size, len, offset);
360 ret = __snprintf_connlabels(buf + offset, len, map, b,
"%s,");
362 BUFFER_SIZE(ret, size, len, offset);
366 ret = snprintf(buf + offset, len,
" ");
367 BUFFER_SIZE(ret, size, len, offset);
372int __snprintf_conntrack_default(
char *buf,
374 const struct nf_conntrack *ct,
375 unsigned int msg_type,
379 int ret = 0, size = 0, offset = 0;
383 ret = snprintf(buf, len,
"%9s ",
"[NEW]");
386 ret = snprintf(buf, len,
"%9s ",
"[UPDATE]");
389 ret = snprintf(buf, len,
"%9s ",
"[DESTROY]");
395 BUFFER_SIZE(ret, size, len, offset);
397 if (flags & NFCT_OF_SHOW_LAYER3) {
398 ret = __snprintf_l3protocol(buf+offset, len, ct);
399 BUFFER_SIZE(ret, size, len, offset);
402 ret = __snprintf_protocol(buf+offset, len, ct);
403 BUFFER_SIZE(ret, size, len, offset);
405 if (test_bit(ATTR_TIMEOUT, ct->head.set)) {
406 ret = __snprintf_timeout(buf+offset, len, ct);
407 BUFFER_SIZE(ret, size, len, offset);
410 if (test_bit(ATTR_TCP_STATE, ct->head.set)) {
411 ret = __snprintf_protoinfo(buf+offset, len, ct);
412 BUFFER_SIZE(ret, size, len, offset);
415 if (test_bit(ATTR_SCTP_STATE, ct->head.set)) {
416 ret = __snprintf_protoinfo_sctp(buf+offset, len, ct);
417 BUFFER_SIZE(ret, size, len, offset);
420 if (test_bit(ATTR_DCCP_STATE, ct->head.set)) {
421 ret = __snprintf_protoinfo_dccp(buf+offset, len, ct);
422 BUFFER_SIZE(ret, size, len, offset);
425 ret = __snprintf_address(buf+offset, len, &ct->head.orig,
427 BUFFER_SIZE(ret, size, len, offset);
429 ret = __snprintf_proto(buf+offset, len, &ct->head.orig);
430 BUFFER_SIZE(ret, size, len, offset);
432 if (test_bit(ATTR_ORIG_ZONE, ct->head.set)) {
433 ret = __snprintf_tuple_zone(buf+offset, len,
"orig", &ct->head.orig);
434 BUFFER_SIZE(ret, size, len, offset);
437 if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set) &&
438 test_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set)) {
439 ret = __snprintf_counters(buf+offset, len, ct, __DIR_ORIG);
440 BUFFER_SIZE(ret, size, len, offset);
443 if (test_bit(ATTR_STATUS, ct->head.set)) {
444 ret = __snprintf_status_not_seen_reply(buf+offset, len, ct);
445 BUFFER_SIZE(ret, size, len, offset);
448 ret = __snprintf_address(buf+offset, len, &ct->repl,
450 BUFFER_SIZE(ret, size, len, offset);
452 ret = __snprintf_proto(buf+offset, len, &ct->repl);
453 BUFFER_SIZE(ret, size, len, offset);
455 if (test_bit(ATTR_REPL_ZONE, ct->head.set)) {
456 ret = __snprintf_tuple_zone(buf+offset, len,
"reply", &ct->repl);
457 BUFFER_SIZE(ret, size, len, offset);
460 if (test_bit(ATTR_REPL_COUNTER_PACKETS, ct->head.set) &&
461 test_bit(ATTR_REPL_COUNTER_BYTES, ct->head.set)) {
462 ret = __snprintf_counters(buf+offset, len, ct, __DIR_REPL);
463 BUFFER_SIZE(ret, size, len, offset);
466 if (test_bit(ATTR_STATUS, ct->head.set)) {
467 ret = __snprintf_status_assured(buf+offset, len, ct);
468 BUFFER_SIZE(ret, size, len, offset);
471 if (test_bit(ATTR_MARK, ct->head.set)) {
472 ret = __snprintf_mark(buf+offset, len, ct);
473 BUFFER_SIZE(ret, size, len, offset);
476 if (test_bit(ATTR_SECMARK, ct->head.set)) {
477 ret = __snprintf_secmark(buf+offset, len, ct);
478 BUFFER_SIZE(ret, size, len, offset);
481 if (test_bit(ATTR_SECCTX, ct->head.set)) {
482 ret = __snprintf_secctx(buf+offset, len, ct);
483 BUFFER_SIZE(ret, size, len, offset);
486 if (test_bit(ATTR_ZONE, ct->head.set)) {
487 ret = __snprintf_zone(buf+offset, len, ct);
488 BUFFER_SIZE(ret, size, len, offset);
491 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
492 ret = __snprintf_timestamp_delta(buf+offset, len, ct);
493 BUFFER_SIZE(ret, size, len, offset);
495 if (flags & NFCT_OF_TIMESTAMP) {
496 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
497 ret = __snprintf_timestamp_start(buf+offset, len, ct);
498 BUFFER_SIZE(ret, size, len, offset);
500 if (test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
501 ret = __snprintf_timestamp_stop(buf+offset, len, ct);
502 BUFFER_SIZE(ret, size, len, offset);
506 if (test_bit(ATTR_HELPER_NAME, ct->head.set)) {
507 ret = __snprintf_helper_name(buf+offset, len, ct);
508 BUFFER_SIZE(ret, size, len, offset);
511 if (test_bit(ATTR_USE, ct->head.set)) {
512 ret = __snprintf_use(buf+offset, len, ct);
513 BUFFER_SIZE(ret, size, len, offset);
516 if (flags & NFCT_OF_ID && test_bit(ATTR_ID, ct->head.set)) {
517 ret = __snprintf_id(buf+offset, len, ct);
518 BUFFER_SIZE(ret, size, len, offset);
521 if (map && test_bit(ATTR_CONNLABELS, ct->head.set)) {
522 ret = __snprintf_clabels(buf+offset, len, ct, map);
523 BUFFER_SIZE(ret, size, len, offset);
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
const char * nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)