1 /* 2 * (C) 2005-2011 by Pablo Neira Ayuso <pablo (at) netfilter.org> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ 9 10 #include "internal/internal.h" 11 12 /* 13 * XML output sample: 14 * 15 * <flow> 16 * <meta direction="original"> 17 * <layer3 protonum="2" protoname="IPv4"> 18 * <src>192.168.0.1</src> 19 * <dst>192.168.0.2</dst> 20 * </layer3> 21 * <layer4 protonum="16" protoname"udp"> 22 * <sport>80</sport> 23 * <dport>56665</dport> 24 * </layer4> 25 * <counters> 26 * <bytes>10</bytes> 27 * <packets>1</packets> 28 * </counters> 29 * </meta> 30 * <meta direction="reply"> 31 * <layer3 protonum="2" protoname="IPv4"> 32 * <src>192.168.0.2</src> 33 * <dst>192.168.0.1</dst> 34 * </layer3> 35 * <layer4 protonum="16" protoname="udp"> 36 * <sport>80</sport> 37 * <dport>56665</dport> 38 * </layer4> 39 * <counters> 40 * <bytes>5029</bytes> 41 * <packets>12</packets> 42 * </counters> 43 * </meta> 44 * <meta direction="independent"> 45 * <state>ESTABLISHED</state> 46 * <timeout>100</timeout> 47 * <mark>1</mark> 48 * <secmark>0</secmark> 49 * <id>453281439</id> 50 * <use>1</use> 51 * <assured/> 52 * </meta> 53 * </flow> 54 */ 55 56 const char *__proto2str(uint8_t protonum) 57 { 58 return proto2str[protonum] ? proto2str[protonum] : "unknown"; 59 } 60 61 const char *__l3proto2str(uint8_t protonum) 62 { 63 return l3proto2str[protonum] ? l3proto2str[protonum] : "unknown"; 64 } 65 66 static int __snprintf_ipv4_xml(char *buf, 67 unsigned int len, 68 const struct __nfct_tuple *tuple, 69 unsigned int type) 70 { 71 struct in_addr addr = { 72 .s_addr = (type == __ADDR_SRC) ? tuple->src.v4 : tuple->dst.v4, 73 }; 74 75 return snprintf(buf, len, "%s", inet_ntoa(addr)); 76 } 77 78 static int __snprintf_ipv6_xml(char *buf, 79 unsigned int len, 80 const struct __nfct_tuple *tuple, 81 unsigned int type) 82 { 83 struct in6_addr addr; 84 static char tmp[INET6_ADDRSTRLEN]; 85 const void *p = (type == __ADDR_SRC) ? &tuple->src.v6 : &tuple->dst.v6; 86 87 memcpy(&addr, p, sizeof(struct in6_addr)); 88 89 if (!inet_ntop(AF_INET6, &addr, tmp, sizeof(tmp))) 90 return -1; 91 92 return snprintf(buf, len, "%s", tmp); 93 } 94 95 int __snprintf_addr_xml(char *buf, unsigned int len, 96 const struct __nfct_tuple *tuple, 97 enum __nfct_addr type) 98 { 99 int ret; 100 unsigned int size = 0, offset = 0; 101 const char *tag = (type == __ADDR_SRC) ? "src" : "dst"; 102 103 ret = snprintf(buf, len, "<%s>", tag); 104 BUFFER_SIZE(ret, size, len, offset); 105 106 switch (tuple->l3protonum) { 107 case AF_INET: 108 ret = __snprintf_ipv4_xml(buf+offset, len, tuple, type); 109 BUFFER_SIZE(ret, size, len, offset); 110 break; 111 case AF_INET6: 112 ret = __snprintf_ipv6_xml(buf+offset, len, tuple, type); 113 BUFFER_SIZE(ret, size, len, offset); 114 break; 115 } 116 117 ret = snprintf(buf+offset, len, "</%s>", tag); 118 BUFFER_SIZE(ret, size, len, offset); 119 120 return size; 121 } 122 123 int __snprintf_proto_xml(char *buf, unsigned int len, 124 const struct __nfct_tuple *tuple, 125 enum __nfct_addr type) 126 { 127 int ret = 0; 128 unsigned int size = 0, offset = 0; 129 130 switch(tuple->protonum) { 131 case IPPROTO_TCP: 132 case IPPROTO_UDP: 133 case IPPROTO_UDPLITE: 134 case IPPROTO_SCTP: 135 case IPPROTO_DCCP: 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); 140 } else { 141 ret = snprintf(buf, len, "<dport>%u</dport>", 142 ntohs(tuple->l4dst.tcp.port)); 143 BUFFER_SIZE(ret, size, len, offset); 144 } 145 break; 146 case IPPROTO_GRE: 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); 151 } else { 152 ret = snprintf(buf, len, "<dstkey>0x%x</dstkey>", 153 ntohs(tuple->l4dst.all)); 154 BUFFER_SIZE(ret, size, len, offset); 155 } 156 break; 157 } 158 159 return ret; 160 } 161 162 static int __snprintf_counters_xml(char *buf, 163 unsigned int len, 164 const struct nf_conntrack *ct, 165 unsigned int type) 166 { 167 int ret; 168 unsigned int size = 0, offset = 0; 169 170 ret = snprintf(buf, len, "<packets>%llu</packets>", 171 (unsigned long long)ct->counters[type].packets); 172 BUFFER_SIZE(ret, size, len, offset); 173 174 ret = snprintf(buf+offset, len, "<bytes>%llu</bytes>", 175 (unsigned long long)ct->counters[type].bytes); 176 BUFFER_SIZE(ret, size, len, offset); 177 178 return size; 179 } 180 181 static int 182 __snprintf_timestamp_start(char *buf, unsigned int len, 183 const struct nf_conntrack *ct) 184 { 185 int ret; 186 unsigned int size = 0, offset = 0; 187 188 ret = snprintf(buf, len, "<start>%llu</start>", 189 (unsigned long long)ct->timestamp.start); 190 BUFFER_SIZE(ret, size, len, offset); 191 192 return size; 193 } 194 195 static int 196 __snprintf_timestamp_stop(char *buf, unsigned int len, 197 const struct nf_conntrack *ct) 198 { 199 int ret; 200 unsigned int size = 0, offset = 0; 201 202 ret = snprintf(buf, len, "<stop>%llu</stop>", 203 (unsigned long long)ct->timestamp.stop); 204 BUFFER_SIZE(ret, size, len, offset); 205 206 return size; 207 } 208 209 static int 210 __snprintf_deltatime_now(char *buf, unsigned int len, 211 const struct nf_conntrack *ct) 212 { 213 int ret; 214 unsigned int size = 0, offset = 0; 215 time_t now, delta_time; 216 217 time(&now); 218 delta_time = now - (time_t)(ct->timestamp.start / NSEC_PER_SEC); 219 220 ret = snprintf(buf+offset, len, "<deltatime>%llu</deltatime>", 221 (unsigned long long)delta_time); 222 BUFFER_SIZE(ret, size, len, offset); 223 224 return size; 225 } 226 227 static int 228 __snprintf_deltatime(char *buf, unsigned int len, const struct nf_conntrack *ct) 229 { 230 int ret; 231 unsigned int size = 0, offset = 0; 232 time_t delta_time = (time_t)((ct->timestamp.stop - 233 ct->timestamp.start) / NSEC_PER_SEC); 234 235 ret = snprintf(buf+offset, len, "<deltatime>%llu</deltatime>", 236 (unsigned long long)delta_time); 237 BUFFER_SIZE(ret, size, len, offset); 238 239 return size; 240 } 241 242 static int 243 __snprintf_helper_name(char *buf, unsigned int len, const struct nf_conntrack *ct) 244 { 245 int ret; 246 unsigned int size = 0, offset = 0; 247 248 ret = snprintf(buf+offset, len, "<helper>%s</helper>", ct->helper_name); 249 BUFFER_SIZE(ret, size, len, offset); 250 251 return size; 252 } 253 254 int 255 __snprintf_localtime_xml(char *buf, unsigned int len, const struct tm *tm) 256 { 257 int ret = 0; 258 unsigned int size = 0, offset = 0; 259 260 ret = snprintf(buf+offset, len, "<hour>%d</hour>", tm->tm_hour); 261 BUFFER_SIZE(ret, size, len, offset); 262 263 ret = snprintf(buf+offset, len, "<min>%02d</min>", tm->tm_min); 264 BUFFER_SIZE(ret, size, len, offset); 265 266 ret = snprintf(buf+offset, len, "<sec>%02d</sec>", tm->tm_sec); 267 BUFFER_SIZE(ret, size, len, offset); 268 269 ret = snprintf(buf+offset, len, "<wday>%d</wday>", tm->tm_wday + 1); 270 BUFFER_SIZE(ret, size, len, offset); 271 272 ret = snprintf(buf+offset, len, "<day>%d</day>", tm->tm_mday); 273 BUFFER_SIZE(ret, size, len, offset); 274 275 ret = snprintf(buf+offset, len, "<month>%d</month>", tm->tm_mon + 1); 276 BUFFER_SIZE(ret, size, len, offset); 277 278 ret = snprintf(buf+offset, len, "<year>%d</year>", 1900 + tm->tm_year); 279 BUFFER_SIZE(ret, size, len, offset); 280 281 return size; 282 } 283 284 static int __snprintf_tuple_xml(char *buf, 285 unsigned int len, 286 const struct nf_conntrack *ct, 287 unsigned int dir, bool zone_incl) 288 { 289 int ret; 290 unsigned int size = 0, offset = 0; 291 const struct __nfct_tuple *tuple = NULL; 292 293 switch(dir) { 294 case __DIR_ORIG: 295 tuple = &ct->head.orig; 296 break; 297 case __DIR_REPL: 298 tuple = &ct->repl; 299 break; 300 } 301 ret = snprintf(buf, len, "<meta direction=\"%s\">", 302 dir == __DIR_ORIG ? "original" : "reply"); 303 BUFFER_SIZE(ret, size, len, offset); 304 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); 309 310 ret = __snprintf_addr_xml(buf+offset, len, tuple, __ADDR_SRC); 311 BUFFER_SIZE(ret, size, len, offset); 312 313 ret = __snprintf_addr_xml(buf+offset, len, tuple, __ADDR_DST); 314 BUFFER_SIZE(ret, size, len, offset); 315 316 ret = snprintf(buf+offset, len, "</layer3>"); 317 BUFFER_SIZE(ret, size, len, offset); 318 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); 323 324 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_ORIG); 325 BUFFER_SIZE(ret, size, len, offset); 326 327 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_REPL); 328 BUFFER_SIZE(ret, size, len, offset); 329 330 ret = snprintf(buf+offset, len, "</layer4>"); 331 BUFFER_SIZE(ret, size, len, offset); 332 333 if (zone_incl) { 334 ret = snprintf(buf+offset, len, "<zone>%u</zone>", tuple->zone); 335 BUFFER_SIZE(ret, size, len, offset); 336 } 337 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); 342 343 ret = __snprintf_counters_xml(buf+offset, len, ct, dir); 344 BUFFER_SIZE(ret, size, len, offset); 345 346 ret = snprintf(buf+offset, len, "</counters>"); 347 BUFFER_SIZE(ret, size, len, offset); 348 } 349 350 ret = snprintf(buf+offset, len, "</meta>"); 351 BUFFER_SIZE(ret, size, len, offset); 352 353 return size; 354 } 355 356 static int 357 __snprintf_clabels_xml(char *buf, unsigned int len, 358 const struct nf_conntrack *ct, struct nfct_labelmap *map) 359 { 360 const struct nfct_bitmask *b = nfct_get_attr(ct, ATTR_CONNLABELS); 361 int ret, size = 0, offset = 0; 362 363 if (!b) 364 return 0; 365 366 ret = snprintf(buf, len, "<labels>"); 367 BUFFER_SIZE(ret, size, len, offset); 368 369 ret = __snprintf_connlabels(buf + offset, len, map, b, "<label>%s</label>"); 370 371 BUFFER_SIZE(ret, size, len, offset); 372 373 ret = snprintf(buf + offset, len, "</labels>"); 374 BUFFER_SIZE(ret, size, len, offset); 375 376 return size; 377 } 378 379 int __snprintf_conntrack_xml(char *buf, 380 unsigned int len, 381 const struct nf_conntrack *ct, 382 const unsigned int msg_type, 383 const unsigned int flags, 384 struct nfct_labelmap *map) 385 { 386 int ret = 0; 387 unsigned int size = 0, offset = 0; 388 389 switch(msg_type) { 390 case NFCT_T_NEW: 391 ret = snprintf(buf, len, "<flow type=\"new\">"); 392 break; 393 case NFCT_T_UPDATE: 394 ret = snprintf(buf, len, "<flow type=\"update\">"); 395 break; 396 case NFCT_T_DESTROY: 397 ret = snprintf(buf, len, "<flow type=\"destroy\">"); 398 break; 399 default: 400 ret = snprintf(buf, len, "<flow>"); 401 break; 402 } 403 404 BUFFER_SIZE(ret, size, len, offset); 405 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); 409 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); 413 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); 430 } 431 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); 438 } 439 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); 446 } 447 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); 454 } 455 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); 460 } 461 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); 465 } 466 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); 470 } 471 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); 476 } 477 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); 482 } 483 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); 487 } 488 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); 492 } 493 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); 497 } 498 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); 503 } 504 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); 509 } 510 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); 516 } 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); 520 } 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); 524 } 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); 529 } 530 } 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); 538 } 539 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); 555 } 556 557 if (flags & NFCT_OF_TIME) { 558 time_t t; 559 struct tm tm; 560 561 t = time(NULL); 562 if (localtime_r(&t, &tm) == NULL) 563 goto err_out; 564 565 ret = snprintf(buf+offset, len, "<when>"); 566 BUFFER_SIZE(ret, size, len, offset); 567 568 ret = __snprintf_localtime_xml(buf+offset, len, &tm); 569 BUFFER_SIZE(ret, size, len, offset); 570 571 ret = snprintf(buf+offset, len, "</when>"); 572 BUFFER_SIZE(ret, size, len, offset); 573 } 574 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); 578 } 579 err_out: 580 ret = snprintf(buf+offset, len, "</flow>"); 581 BUFFER_SIZE(ret, size, len, offset); 582 583 return size; 584 } 585