10 #include "internal/internal.h"
56 const char *__proto2str(uint8_t protonum)
58 return proto2str[protonum] ? proto2str[protonum] :
"unknown";
61 const char *__l3proto2str(uint8_t protonum)
63 return l3proto2str[protonum] ? l3proto2str[protonum] :
"unknown";
66 static int __snprintf_ipv4_xml(
char *buf,
68 const struct __nfct_tuple *tuple,
71 struct in_addr addr = {
72 .s_addr = (type == __ADDR_SRC) ? tuple->src.v4 : tuple->dst.v4,
75 return snprintf(buf, len,
"%s", inet_ntoa(addr));
78 static int __snprintf_ipv6_xml(
char *buf,
80 const struct __nfct_tuple *tuple,
84 static char tmp[INET6_ADDRSTRLEN];
85 const void *p = (type == __ADDR_SRC) ? &tuple->src.v6 : &tuple->dst.v6;
87 memcpy(&addr, p,
sizeof(
struct in6_addr));
89 if (!inet_ntop(AF_INET6, &addr, tmp,
sizeof(tmp)))
92 return snprintf(buf, len,
"%s", tmp);
95 int __snprintf_addr_xml(
char *buf,
unsigned int len,
96 const struct __nfct_tuple *tuple,
97 enum __nfct_addr type)
100 unsigned int size = 0, offset = 0;
101 const char *tag = (type == __ADDR_SRC) ?
"src" :
"dst";
103 ret = snprintf(buf, len,
"<%s>", tag);
104 BUFFER_SIZE(ret, size, len, offset);
106 switch (tuple->l3protonum) {
108 ret = __snprintf_ipv4_xml(buf+offset, len, tuple, type);
109 BUFFER_SIZE(ret, size, len, offset);
112 ret = __snprintf_ipv6_xml(buf+offset, len, tuple, type);
113 BUFFER_SIZE(ret, size, len, offset);
117 ret = snprintf(buf+offset, len,
"</%s>", tag);
118 BUFFER_SIZE(ret, size, len, offset);
123 int __snprintf_proto_xml(
char *buf,
unsigned int len,
124 const struct __nfct_tuple *tuple,
125 enum __nfct_addr type)
128 unsigned int size = 0, offset = 0;
130 switch(tuple->protonum) {
133 case IPPROTO_UDPLITE:
136 if (type == __ADDR_SRC) {
137 ret = snprintf(buf, len,
"<sport>%u</sport>",
138 ntohs(tuple->l4src.tcp.port));
139 BUFFER_SIZE(ret, size, len, offset);
141 ret = snprintf(buf, len,
"<dport>%u</dport>",
142 ntohs(tuple->l4dst.tcp.port));
143 BUFFER_SIZE(ret, size, len, offset);
147 if (type == __ADDR_SRC) {
148 ret = snprintf(buf, len,
"<srckey>0x%x</srckey>",
149 ntohs(tuple->l4src.all));
150 BUFFER_SIZE(ret, size, len, offset);
152 ret = snprintf(buf, len,
"<dstkey>0x%x</dstkey>",
153 ntohs(tuple->l4dst.all));
154 BUFFER_SIZE(ret, size, len, offset);
162 static int __snprintf_counters_xml(
char *buf,
164 const struct nf_conntrack *ct,
168 unsigned int size = 0, offset = 0;
170 ret = snprintf(buf, len,
"<packets>%llu</packets>",
171 (
unsigned long long)ct->counters[type].packets);
172 BUFFER_SIZE(ret, size, len, offset);
174 ret = snprintf(buf+offset, len,
"<bytes>%llu</bytes>",
175 (
unsigned long long)ct->counters[type].bytes);
176 BUFFER_SIZE(ret, size, len, offset);
182 __snprintf_timestamp_start(
char *buf,
unsigned int len,
183 const struct nf_conntrack *ct)
186 unsigned int size = 0, offset = 0;
188 ret = snprintf(buf, len,
"<start>%llu</start>",
189 (
unsigned long long)ct->timestamp.start);
190 BUFFER_SIZE(ret, size, len, offset);
196 __snprintf_timestamp_stop(
char *buf,
unsigned int len,
197 const struct nf_conntrack *ct)
200 unsigned int size = 0, offset = 0;
202 ret = snprintf(buf, len,
"<stop>%llu</stop>",
203 (
unsigned long long)ct->timestamp.stop);
204 BUFFER_SIZE(ret, size, len, offset);
210 __snprintf_deltatime_now(
char *buf,
unsigned int len,
211 const struct nf_conntrack *ct)
214 unsigned int size = 0, offset = 0;
215 time_t now, delta_time;
218 delta_time = now - (time_t)(ct->timestamp.start / NSEC_PER_SEC);
220 ret = snprintf(buf+offset, len,
"<deltatime>%llu</deltatime>",
221 (
unsigned long long)delta_time);
222 BUFFER_SIZE(ret, size, len, offset);
228 __snprintf_deltatime(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
231 unsigned int size = 0, offset = 0;
232 time_t delta_time = (time_t)((ct->timestamp.stop -
233 ct->timestamp.start) / NSEC_PER_SEC);
235 ret = snprintf(buf+offset, len,
"<deltatime>%llu</deltatime>",
236 (
unsigned long long)delta_time);
237 BUFFER_SIZE(ret, size, len, offset);
243 __snprintf_helper_name(
char *buf,
unsigned int len,
const struct nf_conntrack *ct)
246 unsigned int size = 0, offset = 0;
248 ret = snprintf(buf+offset, len,
"<helper>%s</helper>", ct->helper_name);
249 BUFFER_SIZE(ret, size, len, offset);
255 __snprintf_localtime_xml(
char *buf,
unsigned int len,
const struct tm *tm)
258 unsigned int size = 0, offset = 0;
260 ret = snprintf(buf+offset, len,
"<hour>%d</hour>", tm->tm_hour);
261 BUFFER_SIZE(ret, size, len, offset);
263 ret = snprintf(buf+offset, len,
"<min>%02d</min>", tm->tm_min);
264 BUFFER_SIZE(ret, size, len, offset);
266 ret = snprintf(buf+offset, len,
"<sec>%02d</sec>", tm->tm_sec);
267 BUFFER_SIZE(ret, size, len, offset);
269 ret = snprintf(buf+offset, len,
"<wday>%d</wday>", tm->tm_wday + 1);
270 BUFFER_SIZE(ret, size, len, offset);
272 ret = snprintf(buf+offset, len,
"<day>%d</day>", tm->tm_mday);
273 BUFFER_SIZE(ret, size, len, offset);
275 ret = snprintf(buf+offset, len,
"<month>%d</month>", tm->tm_mon + 1);
276 BUFFER_SIZE(ret, size, len, offset);
278 ret = snprintf(buf+offset, len,
"<year>%d</year>", 1900 + tm->tm_year);
279 BUFFER_SIZE(ret, size, len, offset);
284 static int __snprintf_tuple_xml(
char *buf,
286 const struct nf_conntrack *ct,
287 unsigned int dir,
bool zone_incl)
290 unsigned int size = 0, offset = 0;
291 const struct __nfct_tuple *tuple = NULL;
295 tuple = &ct->head.orig;
301 ret = snprintf(buf, len,
"<meta direction=\"%s\">",
302 dir == __DIR_ORIG ?
"original" :
"reply");
303 BUFFER_SIZE(ret, size, len, offset);
305 ret = snprintf(buf+offset, len,
306 "<layer3 protonum=\"%d\" protoname=\"%s\">",
307 tuple->l3protonum, __l3proto2str(tuple->l3protonum));
308 BUFFER_SIZE(ret, size, len, offset);
310 ret = __snprintf_addr_xml(buf+offset, len, tuple, __ADDR_SRC);
311 BUFFER_SIZE(ret, size, len, offset);
313 ret = __snprintf_addr_xml(buf+offset, len, tuple, __ADDR_DST);
314 BUFFER_SIZE(ret, size, len, offset);
316 ret = snprintf(buf+offset, len,
"</layer3>");
317 BUFFER_SIZE(ret, size, len, offset);
319 ret = snprintf(buf+offset, len,
320 "<layer4 protonum=\"%d\" protoname=\"%s\">",
321 tuple->protonum, __proto2str(tuple->protonum));
322 BUFFER_SIZE(ret, size, len, offset);
324 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_ORIG);
325 BUFFER_SIZE(ret, size, len, offset);
327 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_REPL);
328 BUFFER_SIZE(ret, size, len, offset);
330 ret = snprintf(buf+offset, len,
"</layer4>");
331 BUFFER_SIZE(ret, size, len, offset);
334 ret = snprintf(buf+offset, len,
"<zone>%u</zone>", tuple->zone);
335 BUFFER_SIZE(ret, size, len, offset);
338 if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->head.set) &&
339 test_bit(ATTR_ORIG_COUNTER_BYTES, ct->head.set)) {
340 ret = snprintf(buf+offset, len,
"<counters>");
341 BUFFER_SIZE(ret, size, len, offset);
343 ret = __snprintf_counters_xml(buf+offset, len, ct, dir);
344 BUFFER_SIZE(ret, size, len, offset);
346 ret = snprintf(buf+offset, len,
"</counters>");
347 BUFFER_SIZE(ret, size, len, offset);
350 ret = snprintf(buf+offset, len,
"</meta>");
351 BUFFER_SIZE(ret, size, len, offset);
357 __snprintf_clabels_xml(
char *buf,
unsigned int len,
360 const struct nfct_bitmask *b =
nfct_get_attr(ct, ATTR_CONNLABELS);
361 int ret, size = 0, offset = 0;
366 ret = snprintf(buf, len,
"<labels>");
367 BUFFER_SIZE(ret, size, len, offset);
369 ret = __snprintf_connlabels(buf + offset, len, map, b,
"<label>%s</label>");
371 BUFFER_SIZE(ret, size, len, offset);
373 ret = snprintf(buf + offset, len,
"</labels>");
374 BUFFER_SIZE(ret, size, len, offset);
379 int __snprintf_conntrack_xml(
char *buf,
381 const struct nf_conntrack *ct,
382 const unsigned int msg_type,
383 const unsigned int flags,
387 unsigned int size = 0, offset = 0;
391 ret = snprintf(buf, len,
"<flow type=\"new\">");
394 ret = snprintf(buf, len,
"<flow type=\"update\">");
397 ret = snprintf(buf, len,
"<flow type=\"destroy\">");
400 ret = snprintf(buf, len,
"<flow>");
404 BUFFER_SIZE(ret, size, len, offset);
406 ret = __snprintf_tuple_xml(buf+offset, len, ct, __DIR_ORIG,
407 test_bit(ATTR_ORIG_ZONE, ct->head.set));
408 BUFFER_SIZE(ret, size, len, offset);
410 ret = __snprintf_tuple_xml(buf+offset, len, ct, __DIR_REPL,
411 test_bit(ATTR_REPL_ZONE, ct->head.set));
412 BUFFER_SIZE(ret, size, len, offset);
414 if (test_bit(ATTR_TCP_STATE, ct->head.set) ||
415 test_bit(ATTR_SCTP_STATE, ct->head.set) ||
416 test_bit(ATTR_DCCP_STATE, ct->head.set) ||
417 test_bit(ATTR_TIMEOUT, ct->head.set) ||
418 test_bit(ATTR_MARK, ct->head.set) ||
419 test_bit(ATTR_SECMARK, ct->head.set) ||
420 test_bit(ATTR_ZONE, ct->head.set) ||
421 test_bit(ATTR_USE, ct->head.set) ||
422 test_bit(ATTR_STATUS, ct->head.set) ||
423 test_bit(ATTR_ID, ct->head.set) ||
424 test_bit(ATTR_CONNLABELS, ct->head.set) ||
425 test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
426 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
427 ret = snprintf(buf+offset, len,
428 "<meta direction=\"independent\">");
429 BUFFER_SIZE(ret, size, len, offset);
432 if (test_bit(ATTR_TCP_STATE, ct->head.set)) {
433 ret = snprintf(buf+offset, len,
"<state>%s</state>",
434 ct->protoinfo.tcp.state < TCP_CONNTRACK_MAX ?
435 states[ct->protoinfo.tcp.state] :
436 states[TCP_CONNTRACK_NONE]);
437 BUFFER_SIZE(ret, size, len, offset);
440 if (test_bit(ATTR_SCTP_STATE, ct->head.set)) {
441 ret = snprintf(buf+offset, len,
"<state>%s</state>",
442 ct->protoinfo.sctp.state < SCTP_CONNTRACK_MAX ?
443 states[ct->protoinfo.sctp.state] :
444 states[SCTP_CONNTRACK_NONE]);
445 BUFFER_SIZE(ret, size, len, offset);
448 if (test_bit(ATTR_DCCP_STATE, ct->head.set)) {
449 ret = snprintf(buf+offset, len,
"<state>%s</state>",
450 ct->protoinfo.sctp.state < DCCP_CONNTRACK_MAX ?
451 states[ct->protoinfo.dccp.state] :
452 states[DCCP_CONNTRACK_NONE]);
453 BUFFER_SIZE(ret, size, len, offset);
456 if (test_bit(ATTR_TIMEOUT, ct->head.set)) {
457 ret = snprintf(buf+offset, len,
458 "<timeout>%u</timeout>", ct->timeout);
459 BUFFER_SIZE(ret, size, len, offset);
462 if (test_bit(ATTR_MARK, ct->head.set)) {
463 ret = snprintf(buf+offset, len,
"<mark>%u</mark>", ct->mark);
464 BUFFER_SIZE(ret, size, len, offset);
467 if (map && test_bit(ATTR_CONNLABELS, ct->head.set)) {
468 ret = __snprintf_clabels_xml(buf+offset, len, ct, map);
469 BUFFER_SIZE(ret, size, len, offset);
472 if (test_bit(ATTR_SECMARK, ct->head.set)) {
473 ret = snprintf(buf+offset, len,
474 "<secmark>%u</secmark>", ct->secmark);
475 BUFFER_SIZE(ret, size, len, offset);
478 if (test_bit(ATTR_SECCTX, ct->head.set)) {
479 ret = snprintf(buf+offset, len,
480 "<secctx>%s</secctx>", ct->secctx);
481 BUFFER_SIZE(ret, size, len, offset);
484 if (test_bit(ATTR_ZONE, ct->head.set)) {
485 ret = snprintf(buf+offset, len,
"<zone>%u</zone>", ct->zone);
486 BUFFER_SIZE(ret, size, len, offset);
489 if (test_bit(ATTR_USE, ct->head.set)) {
490 ret = snprintf(buf+offset, len,
"<use>%u</use>", ct->use);
491 BUFFER_SIZE(ret, size, len, offset);
494 if (test_bit(ATTR_ID, ct->head.set)) {
495 ret = snprintf(buf+offset, len,
"<id>%u</id>", ct->id);
496 BUFFER_SIZE(ret, size, len, offset);
499 if (test_bit(ATTR_STATUS, ct->head.set)
500 && ct->status & IPS_ASSURED) {
501 ret = snprintf(buf+offset, len,
"<assured/>");
502 BUFFER_SIZE(ret, size, len, offset);
505 if (test_bit(ATTR_STATUS, ct->head.set)
506 && !(ct->status & IPS_SEEN_REPLY)) {
507 ret = snprintf(buf+offset, len,
"<unreplied/>");
508 BUFFER_SIZE(ret, size, len, offset);
511 if (flags & NFCT_OF_TIMESTAMP) {
512 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
513 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
514 ret = snprintf(buf+offset, len,
"<timestamp>");
515 BUFFER_SIZE(ret, size, len, offset);
517 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
518 ret = __snprintf_timestamp_start(buf+offset, len, ct);
519 BUFFER_SIZE(ret, size, len, offset);
521 if (test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
522 ret = __snprintf_timestamp_stop(buf+offset, len, ct);
523 BUFFER_SIZE(ret, size, len, offset);
525 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
526 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
527 ret = snprintf(buf+offset, len,
"</timestamp>");
528 BUFFER_SIZE(ret, size, len, offset);
531 if (test_bit(ATTR_TIMESTAMP_START, ct->head.set) &&
532 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
533 ret = __snprintf_deltatime(buf+offset, len, ct);
534 BUFFER_SIZE(ret, size, len, offset);
535 }
else if (test_bit(ATTR_TIMESTAMP_START, ct->head.set)) {
536 ret = __snprintf_deltatime_now(buf+offset, len, ct);
537 BUFFER_SIZE(ret, size, len, offset);
540 if (test_bit(ATTR_TCP_STATE, ct->head.set) ||
541 test_bit(ATTR_SCTP_STATE, ct->head.set) ||
542 test_bit(ATTR_DCCP_STATE, ct->head.set) ||
543 test_bit(ATTR_TIMEOUT, ct->head.set) ||
544 test_bit(ATTR_MARK, ct->head.set) ||
545 test_bit(ATTR_SECMARK, ct->head.set) ||
546 test_bit(ATTR_ZONE, ct->head.set) ||
547 test_bit(ATTR_USE, ct->head.set) ||
548 test_bit(ATTR_STATUS, ct->head.set) ||
549 test_bit(ATTR_ID, ct->head.set) ||
550 test_bit(ATTR_CONNLABELS, ct->head.set) ||
551 test_bit(ATTR_TIMESTAMP_START, ct->head.set) ||
552 test_bit(ATTR_TIMESTAMP_STOP, ct->head.set)) {
553 ret = snprintf(buf+offset, len,
"</meta>");
554 BUFFER_SIZE(ret, size, len, offset);
557 if (flags & NFCT_OF_TIME) {
562 if (localtime_r(&t, &tm) == NULL)
565 ret = snprintf(buf+offset, len,
"<when>");
566 BUFFER_SIZE(ret, size, len, offset);
568 ret = __snprintf_localtime_xml(buf+offset, len, &tm);
569 BUFFER_SIZE(ret, size, len, offset);
571 ret = snprintf(buf+offset, len,
"</when>");
572 BUFFER_SIZE(ret, size, len, offset);
575 if (test_bit(ATTR_HELPER_NAME, ct->head.set)) {
576 ret = __snprintf_helper_name(buf+offset, len, ct);
577 BUFFER_SIZE(ret, size, len, offset);
580 ret = snprintf(buf+offset, len,
"</flow>");
581 BUFFER_SIZE(ret, size, len, offset);
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)