10#include "internal/internal.h"
56const char *__proto2str(uint8_t protonum)
58 const char *str = NULL;
60 if (protonum < ARRAY_SIZE(proto2str))
61 str = proto2str[protonum];
69const char *__l3proto2str(uint8_t protonum)
71 const char *str = NULL;
73 if (protonum < ARRAY_SIZE(l3proto2str))
74 str = l3proto2str[protonum];
82static int __snprintf_ipv4_xml(
char *buf,
84 const struct __nfct_tuple *tuple,
87 struct in_addr addr = {
88 .s_addr = (type == __ADDR_SRC) ? tuple->src.v4 : tuple->dst.v4,
91 return snprintf(buf, len,
"%s", inet_ntoa(addr));
94static int __snprintf_ipv6_xml(
char *buf,
96 const struct __nfct_tuple *tuple,
100 static char tmp[INET6_ADDRSTRLEN];
101 const void *p = (type == __ADDR_SRC) ? &tuple->src.v6 : &tuple->dst.v6;
103 memcpy(&addr, p,
sizeof(
struct in6_addr));
105 if (!inet_ntop(AF_INET6, &addr, tmp,
sizeof(tmp)))
108 return snprintf(buf, len,
"%s", tmp);
111int __snprintf_addr_xml(
char *buf,
unsigned int len,
112 const struct __nfct_tuple *tuple,
113 enum __nfct_addr type)
116 unsigned int size = 0, offset = 0;
117 const char *tag = (type == __ADDR_SRC) ?
"src" :
"dst";
119 ret = snprintf(buf, len,
"<%s>", tag);
120 BUFFER_SIZE(ret, size, len, offset);
122 switch (tuple->l3protonum) {
124 ret = __snprintf_ipv4_xml(buf+offset, len, tuple, type);
125 BUFFER_SIZE(ret, size, len, offset);
128 ret = __snprintf_ipv6_xml(buf+offset, len, tuple, type);
129 BUFFER_SIZE(ret, size, len, offset);
133 ret = snprintf(buf+offset, len,
"</%s>", tag);
134 BUFFER_SIZE(ret, size, len, offset);
139int __snprintf_proto_xml(
char *buf,
unsigned int len,
140 const struct __nfct_tuple *tuple,
141 enum __nfct_addr type)
144 unsigned int size = 0, offset = 0;
146 switch(tuple->protonum) {
149 case IPPROTO_UDPLITE:
152 if (type == __ADDR_SRC) {
153 ret = snprintf(buf, len,
"<sport>%u</sport>",
154 ntohs(tuple->l4src.tcp.port));
155 BUFFER_SIZE(ret, size, len, offset);
157 ret = snprintf(buf, len,
"<dport>%u</dport>",
158 ntohs(tuple->l4dst.tcp.port));
159 BUFFER_SIZE(ret, size, len, offset);
163 if (type == __ADDR_SRC) {
164 ret = snprintf(buf, len,
"<srckey>0x%x</srckey>",
165 ntohs(tuple->l4src.all));
166 BUFFER_SIZE(ret, size, len, offset);
168 ret = snprintf(buf, len,
"<dstkey>0x%x</dstkey>",
169 ntohs(tuple->l4dst.all));
170 BUFFER_SIZE(ret, size, len, offset);
178static int __snprintf_counters_xml(
char *buf,
180 const struct nf_conntrack *ct,
184 unsigned int size = 0, offset = 0;
186 ret = snprintf(buf, len,
"<packets>%llu</packets>",
187 (
unsigned long long)ct->counters[type].packets);
188 BUFFER_SIZE(ret, size, len, offset);
190 ret = snprintf(buf+offset, len,
"<bytes>%llu</bytes>",
191 (
unsigned long long)ct->counters[type].bytes);
192 BUFFER_SIZE(ret, size, len, offset);
198__snprintf_timestamp_start(
char *buf,
unsigned int len,
199 const struct nf_conntrack *ct)
202 unsigned int size = 0, offset = 0;
204 ret = snprintf(buf, len,
"<start>%llu</start>",
205 (
unsigned long long)ct->timestamp.start);
206 BUFFER_SIZE(ret, size, len, offset);
212__snprintf_timestamp_stop(
char *buf,
unsigned int len,
213 const struct nf_conntrack *ct)
216 unsigned int size = 0, offset = 0;
218 ret = snprintf(buf, len,
"<stop>%llu</stop>",
219 (
unsigned long long)ct->timestamp.stop);
220 BUFFER_SIZE(ret, size, len, offset);
226__snprintf_deltatime_now(
char *buf,
unsigned int len,
227 const struct nf_conntrack *ct)
230 unsigned int size = 0, offset = 0;
231 time_t now, delta_time;
234 delta_time = now - (time_t)(ct->timestamp.start / NSEC_PER_SEC);
236 ret = snprintf(buf+offset, len,
"<deltatime>%llu</deltatime>",
237 (
unsigned long long)delta_time);
238 BUFFER_SIZE(ret, size, len, offset);
244__snprintf_deltatime(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
247 unsigned int size = 0, offset = 0;
248 time_t delta_time = (time_t)((ct->timestamp.stop -
249 ct->timestamp.start) / NSEC_PER_SEC);
251 ret = snprintf(buf+offset, len,
"<deltatime>%llu</deltatime>",
252 (
unsigned long long)delta_time);
253 BUFFER_SIZE(ret, size, len, offset);
259__snprintf_helper_name(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
262 unsigned int size = 0, offset = 0;
264 ret = snprintf(buf+offset, len,
"<helper>%s</helper>", ct->helper_name);
265 BUFFER_SIZE(ret, size, len, offset);
271__snprintf_localtime_xml(
char *buf,
unsigned int len,
const struct tm *tm)
274 unsigned int size = 0, offset = 0;
276 ret = snprintf(buf+offset, len,
"<hour>%d</hour>", tm->tm_hour);
277 BUFFER_SIZE(ret, size, len, offset);
279 ret = snprintf(buf+offset, len,
"<min>%02d</min>", tm->tm_min);
280 BUFFER_SIZE(ret, size, len, offset);
282 ret = snprintf(buf+offset, len,
"<sec>%02d</sec>", tm->tm_sec);
283 BUFFER_SIZE(ret, size, len, offset);
285 ret = snprintf(buf+offset, len,
"<wday>%d</wday>", tm->tm_wday + 1);
286 BUFFER_SIZE(ret, size, len, offset);
288 ret = snprintf(buf+offset, len,
"<day>%d</day>", tm->tm_mday);
289 BUFFER_SIZE(ret, size, len, offset);
291 ret = snprintf(buf+offset, len,
"<month>%d</month>", tm->tm_mon + 1);
292 BUFFER_SIZE(ret, size, len, offset);
294 ret = snprintf(buf+offset, len,
"<year>%d</year>", 1900 + tm->tm_year);
295 BUFFER_SIZE(ret, size, len, offset);
300static int __snprintf_tuple_xml(
char *buf,
302 const struct nf_conntrack *ct,
303 unsigned int dir,
bool zone_incl)
306 unsigned int size = 0, offset = 0;
307 const struct __nfct_tuple *tuple = NULL;
311 tuple = &ct->head.orig;
317 ret = snprintf(buf, len,
"<meta direction=\"%s\">",
318 dir == __DIR_ORIG ?
"original" :
"reply");
319 BUFFER_SIZE(ret, size, len, offset);
321 ret = snprintf(buf+offset, len,
322 "<layer3 protonum=\"%d\" protoname=\"%s\">",
323 tuple->l3protonum, __l3proto2str(tuple->l3protonum));
324 BUFFER_SIZE(ret, size, len, offset);
326 ret = __snprintf_addr_xml(buf+offset, len, tuple, __ADDR_SRC);
327 BUFFER_SIZE(ret, size, len, offset);
329 ret = __snprintf_addr_xml(buf+offset, len, tuple, __ADDR_DST);
330 BUFFER_SIZE(ret, size, len, offset);
332 ret = snprintf(buf+offset, len,
"</layer3>");
333 BUFFER_SIZE(ret, size, len, offset);
335 ret = snprintf(buf+offset, len,
336 "<layer4 protonum=\"%d\" protoname=\"%s\">",
337 tuple->protonum, __proto2str(tuple->protonum));
338 BUFFER_SIZE(ret, size, len, offset);
340 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_ORIG);
341 BUFFER_SIZE(ret, size, len, offset);
343 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_REPL);
344 BUFFER_SIZE(ret, size, len, offset);
346 ret = snprintf(buf+offset, len,
"</layer4>");
347 BUFFER_SIZE(ret, size, len, offset);
350 ret = snprintf(buf+offset, len,
"<zone>%u</zone>", tuple->zone);
351 BUFFER_SIZE(ret, size, len, offset);
354 if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set) &&
355 test_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set)) {
356 ret = snprintf(buf+offset, len,
"<counters>");
357 BUFFER_SIZE(ret, size, len, offset);
359 ret = __snprintf_counters_xml(buf+offset, len, ct, dir);
360 BUFFER_SIZE(ret, size, len, offset);
362 ret = snprintf(buf+offset, len,
"</counters>");
363 BUFFER_SIZE(ret, size, len, offset);
366 ret = snprintf(buf+offset, len,
"</meta>");
367 BUFFER_SIZE(ret, size, len, offset);
373__snprintf_clabels_xml(
char *buf,
unsigned int len,
376 const struct nfct_bitmask *b =
nfct_get_attr(ct, ATTR_CONNLABELS);
377 int ret, size = 0, offset = 0;
382 ret = snprintf(buf, len,
"<labels>");
383 BUFFER_SIZE(ret, size, len, offset);
385 ret = __snprintf_connlabels(buf + offset, len, map, b,
"<label>%s</label>");
387 BUFFER_SIZE(ret, size, len, offset);
389 ret = snprintf(buf + offset, len,
"</labels>");
390 BUFFER_SIZE(ret, size, len, offset);
395int __snprintf_conntrack_xml(
char *buf,
397 const struct nf_conntrack *ct,
398 const unsigned int msg_type,
399 const unsigned int flags,
403 unsigned int size = 0, offset = 0;
407 ret = snprintf(buf, len,
"<flow type=\"new\">");
410 ret = snprintf(buf, len,
"<flow type=\"update\">");
413 ret = snprintf(buf, len,
"<flow type=\"destroy\">");
416 ret = snprintf(buf, len,
"<flow>");
420 BUFFER_SIZE(ret, size, len, offset);
422 ret = __snprintf_tuple_xml(buf+offset, len, ct, __DIR_ORIG,
423 test_bit(ATTR_ORIG_ZONE, ct->head.set));
424 BUFFER_SIZE(ret, size, len, offset);
426 ret = __snprintf_tuple_xml(buf+offset, len, ct, __DIR_REPL,
427 test_bit(ATTR_REPL_ZONE, ct->head.set));
428 BUFFER_SIZE(ret, size, len, offset);
430 if (test_bit(ATTR_TCP_STATE, ct->head.set) ||
431 test_bit(ATTR_SCTP_STATE, ct->head.set) ||
432 test_bit(ATTR_DCCP_STATE, ct->head.set) ||
433 test_bit(ATTR_TIMEOUT, ct->head.set) ||
434 test_bit(ATTR_MARK, ct->head.set) ||
435 test_bit(ATTR_SECMARK, ct->head.set) ||
436 test_bit(ATTR_ZONE, ct->head.set) ||
437 test_bit(ATTR_USE, ct->head.set) ||
438 test_bit(ATTR_STATUS, ct->head.set) ||
439 test_bit(ATTR_ID, ct->head.set) ||
440 test_bit(ATTR_CONNLABELS, ct->head.set) ||
441 test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
442 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
443 ret = snprintf(buf+offset, len,
444 "<meta direction=\"independent\">");
445 BUFFER_SIZE(ret, size, len, offset);
448 if (test_bit(ATTR_TCP_STATE, ct->head.set)) {
449 ret = snprintf(buf+offset, len,
"<state>%s</state>",
450 ct->protoinfo.tcp.state < TCP_CONNTRACK_MAX ?
451 states[ct->protoinfo.tcp.state] :
452 states[TCP_CONNTRACK_NONE]);
453 BUFFER_SIZE(ret, size, len, offset);
456 if (test_bit(ATTR_SCTP_STATE, ct->head.set)) {
457 ret = snprintf(buf+offset, len,
"<state>%s</state>",
458 ct->protoinfo.sctp.state < SCTP_CONNTRACK_MAX ?
459 states[ct->protoinfo.sctp.state] :
460 states[SCTP_CONNTRACK_NONE]);
461 BUFFER_SIZE(ret, size, len, offset);
464 if (test_bit(ATTR_DCCP_STATE, ct->head.set)) {
465 ret = snprintf(buf+offset, len,
"<state>%s</state>",
466 ct->protoinfo.sctp.state < DCCP_CONNTRACK_MAX ?
467 states[ct->protoinfo.dccp.state] :
468 states[DCCP_CONNTRACK_NONE]);
469 BUFFER_SIZE(ret, size, len, offset);
472 if (test_bit(ATTR_TIMEOUT, ct->head.set)) {
473 ret = snprintf(buf+offset, len,
474 "<timeout>%u</timeout>", ct->timeout);
475 BUFFER_SIZE(ret, size, len, offset);
478 if (test_bit(ATTR_MARK, ct->head.set)) {
479 ret = snprintf(buf+offset, len,
"<mark>%u</mark>", ct->mark);
480 BUFFER_SIZE(ret, size, len, offset);
483 if (map && test_bit(ATTR_CONNLABELS, ct->head.set)) {
484 ret = __snprintf_clabels_xml(buf+offset, len, ct, map);
485 BUFFER_SIZE(ret, size, len, offset);
488 if (test_bit(ATTR_SECMARK, ct->head.set)) {
489 ret = snprintf(buf+offset, len,
490 "<secmark>%u</secmark>", ct->secmark);
491 BUFFER_SIZE(ret, size, len, offset);
494 if (test_bit(ATTR_SECCTX, ct->head.set)) {
495 ret = snprintf(buf+offset, len,
496 "<secctx>%s</secctx>", ct->secctx);
497 BUFFER_SIZE(ret, size, len, offset);
500 if (test_bit(ATTR_ZONE, ct->head.set)) {
501 ret = snprintf(buf+offset, len,
"<zone>%u</zone>", ct->zone);
502 BUFFER_SIZE(ret, size, len, offset);
505 if (test_bit(ATTR_USE, ct->head.set)) {
506 ret = snprintf(buf+offset, len,
"<use>%u</use>", ct->use);
507 BUFFER_SIZE(ret, size, len, offset);
510 if (test_bit(ATTR_ID, ct->head.set)) {
511 ret = snprintf(buf+offset, len,
"<id>%u</id>", ct->id);
512 BUFFER_SIZE(ret, size, len, offset);
515 if (test_bit(ATTR_STATUS, ct->head.set)
516 && ct->status & IPS_ASSURED) {
517 ret = snprintf(buf+offset, len,
"<assured/>");
518 BUFFER_SIZE(ret, size, len, offset);
521 if (test_bit(ATTR_STATUS, ct->head.set)
522 && !(ct->status & IPS_SEEN_REPLY)) {
523 ret = snprintf(buf+offset, len,
"<unreplied/>");
524 BUFFER_SIZE(ret, size, len, offset);
527 if (flags & NFCT_OF_TIMESTAMP) {
528 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
529 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
530 ret = snprintf(buf+offset, len,
"<timestamp>");
531 BUFFER_SIZE(ret, size, len, offset);
533 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
534 ret = __snprintf_timestamp_start(buf+offset, len, ct);
535 BUFFER_SIZE(ret, size, len, offset);
537 if (test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
538 ret = __snprintf_timestamp_stop(buf+offset, len, ct);
539 BUFFER_SIZE(ret, size, len, offset);
541 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
542 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
543 ret = snprintf(buf+offset, len,
"</timestamp>");
544 BUFFER_SIZE(ret, size, len, offset);
547 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set) &&
548 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
549 ret = __snprintf_deltatime(buf+offset, len, ct);
550 BUFFER_SIZE(ret, size, len, offset);
551 }
else if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
552 ret = __snprintf_deltatime_now(buf+offset, len, ct);
553 BUFFER_SIZE(ret, size, len, offset);
556 if (test_bit(ATTR_TCP_STATE, ct->head.set) ||
557 test_bit(ATTR_SCTP_STATE, ct->head.set) ||
558 test_bit(ATTR_DCCP_STATE, ct->head.set) ||
559 test_bit(ATTR_TIMEOUT, ct->head.set) ||
560 test_bit(ATTR_MARK, ct->head.set) ||
561 test_bit(ATTR_SECMARK, ct->head.set) ||
562 test_bit(ATTR_ZONE, ct->head.set) ||
563 test_bit(ATTR_USE, ct->head.set) ||
564 test_bit(ATTR_STATUS, ct->head.set) ||
565 test_bit(ATTR_ID, ct->head.set) ||
566 test_bit(ATTR_CONNLABELS, ct->head.set) ||
567 test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
568 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
569 ret = snprintf(buf+offset, len,
"</meta>");
570 BUFFER_SIZE(ret, size, len, offset);
573 if (flags & NFCT_OF_TIME) {
578 if (localtime_r(&t, &tm) == NULL)
581 ret = snprintf(buf+offset, len,
"<when>");
582 BUFFER_SIZE(ret, size, len, offset);
584 ret = __snprintf_localtime_xml(buf+offset, len, &tm);
585 BUFFER_SIZE(ret, size, len, offset);
587 ret = snprintf(buf+offset, len,
"</when>");
588 BUFFER_SIZE(ret, size, len, offset);
591 if (test_bit(ATTR_HELPER_NAME, ct->head.set)) {
592 ret = __snprintf_helper_name(buf+offset, len, ct);
593 BUFFER_SIZE(ret, size, len, offset);
596 ret = snprintf(buf+offset, len,
"</flow>");
597 BUFFER_SIZE(ret, size, len, offset);
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)