00001
00002
00003
00004
00005
00006
00007
00008 #include "internal/internal.h"
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 enum {
00055 __ADDR_SRC = 0,
00056 __ADDR_DST,
00057 };
00058
00059 static const char *__proto2str(u_int8_t protonum)
00060 {
00061 return proto2str[protonum] ? proto2str[protonum] : "unknown";
00062 }
00063
00064 static const char *__l3proto2str(u_int8_t protonum)
00065 {
00066 return l3proto2str[protonum] ? l3proto2str[protonum] : "unknown";
00067 }
00068
00069 static int __snprintf_ipv4_xml(char *buf,
00070 unsigned int len,
00071 const struct __nfct_tuple *tuple,
00072 unsigned int type)
00073 {
00074 struct in_addr addr = {
00075 .s_addr = (type == __ADDR_SRC) ? tuple->src.v4 : tuple->dst.v4,
00076 };
00077
00078 return snprintf(buf, len, "%s", inet_ntoa(addr));
00079 }
00080
00081 static int __snprintf_ipv6_xml(char *buf,
00082 unsigned int len,
00083 const struct __nfct_tuple *tuple,
00084 unsigned int type)
00085 {
00086 struct in6_addr addr;
00087 static char tmp[INET6_ADDRSTRLEN];
00088 const void *p = (type == __ADDR_SRC) ? &tuple->src.v6 : &tuple->dst.v6;
00089
00090 memcpy(&addr, p, sizeof(struct in6_addr));
00091
00092 if (!inet_ntop(AF_INET6, &addr, tmp, sizeof(tmp)))
00093 return -1;
00094
00095 return snprintf(buf, len, "%s", tmp);
00096 }
00097
00098 static int __snprintf_addr_xml(char *buf,
00099 unsigned int len,
00100 const struct __nfct_tuple *tuple,
00101 unsigned int type)
00102 {
00103 int ret;
00104 unsigned int size = 0, offset = 0;
00105
00106 switch(type) {
00107 case __ADDR_SRC:
00108 ret = snprintf(buf, len, "<src>");
00109 BUFFER_SIZE(ret, size, len, offset);
00110 break;
00111 case __ADDR_DST:
00112 ret = snprintf(buf+offset, len, "<dst>");
00113 BUFFER_SIZE(ret, size, len, offset);
00114 break;
00115 }
00116
00117 switch (tuple->l3protonum) {
00118 case AF_INET:
00119 ret = __snprintf_ipv4_xml(buf+offset, len, tuple, type);
00120 BUFFER_SIZE(ret, size, len, offset);
00121 break;
00122 case AF_INET6:
00123 ret = __snprintf_ipv6_xml(buf+offset, len, tuple, type);
00124 BUFFER_SIZE(ret, size, len, offset);
00125 break;
00126 }
00127
00128 switch(type) {
00129 case __ADDR_SRC:
00130 ret = snprintf(buf+offset, len, "</src>");
00131 BUFFER_SIZE(ret, size, len, offset);
00132 break;
00133 case __ADDR_DST:
00134 ret = snprintf(buf+offset, len, "</dst>");
00135 BUFFER_SIZE(ret, size, len, offset);
00136 break;
00137 }
00138
00139 return size;
00140 }
00141
00142 static int __snprintf_proto_xml(char *buf,
00143 unsigned int len,
00144 const struct __nfct_tuple *tuple,
00145 unsigned int type)
00146 {
00147 int ret = 0;
00148 unsigned int size = 0, offset = 0;
00149
00150 switch(tuple->protonum) {
00151 case IPPROTO_TCP:
00152 case IPPROTO_UDP:
00153 case IPPROTO_UDPLITE:
00154 case IPPROTO_SCTP:
00155 case IPPROTO_DCCP:
00156 if (type == __ADDR_SRC) {
00157 ret = snprintf(buf, len, "<sport>%u</sport>",
00158 ntohs(tuple->l4src.tcp.port));
00159 BUFFER_SIZE(ret, size, len, offset);
00160 } else {
00161 ret = snprintf(buf, len, "<dport>%u</dport>",
00162 ntohs(tuple->l4dst.tcp.port));
00163 BUFFER_SIZE(ret, size, len, offset);
00164 }
00165 break;
00166 case IPPROTO_GRE:
00167 if (type == __ADDR_SRC) {
00168 ret = snprintf(buf, len, "<srckey>0x%x</srckey>",
00169 ntohs(tuple->l4src.all));
00170 BUFFER_SIZE(ret, size, len, offset);
00171 } else {
00172 ret = snprintf(buf, len, "<dstkey>0x%x</dstkey>",
00173 ntohs(tuple->l4dst.all));
00174 BUFFER_SIZE(ret, size, len, offset);
00175 }
00176 break;
00177 }
00178
00179 return ret;
00180 }
00181
00182 static int __snprintf_counters_xml(char *buf,
00183 unsigned int len,
00184 const struct nf_conntrack *ct,
00185 unsigned int type)
00186 {
00187 int ret;
00188 unsigned int size = 0, offset = 0;
00189
00190 ret = snprintf(buf, len, "<packets>%llu</packets>",
00191 (unsigned long long)ct->counters[type].packets);
00192 BUFFER_SIZE(ret, size, len, offset);
00193
00194 ret = snprintf(buf+offset, len, "<bytes>%llu</bytes>",
00195 (unsigned long long)ct->counters[type].bytes);
00196 BUFFER_SIZE(ret, size, len, offset);
00197
00198 return size;
00199 }
00200
00201 static int __snprintf_tuple_xml(char *buf,
00202 unsigned int len,
00203 const struct nf_conntrack *ct,
00204 unsigned int dir)
00205 {
00206 int ret;
00207 unsigned int size = 0, offset = 0;
00208 const struct __nfct_tuple *tuple = &ct->tuple[dir];
00209
00210 ret = snprintf(buf, len, "<meta direction=\"%s\">",
00211 dir == __DIR_ORIG ? "original" : "reply");
00212 BUFFER_SIZE(ret, size, len, offset);
00213
00214 ret = snprintf(buf+offset, len,
00215 "<layer3 protonum=\"%d\" protoname=\"%s\">",
00216 tuple->l3protonum, __l3proto2str(tuple->l3protonum));
00217 BUFFER_SIZE(ret, size, len, offset);
00218
00219 ret = __snprintf_addr_xml(buf+offset, len, tuple, __DIR_ORIG);
00220 BUFFER_SIZE(ret, size, len, offset);
00221
00222 ret = __snprintf_addr_xml(buf+offset, len, tuple, __DIR_REPL);
00223 BUFFER_SIZE(ret, size, len, offset);
00224
00225 ret = snprintf(buf+offset, len, "</layer3>");
00226 BUFFER_SIZE(ret, size, len, offset);
00227
00228 ret = snprintf(buf+offset, len,
00229 "<layer4 protonum=\"%d\" protoname=\"%s\">",
00230 tuple->protonum, __proto2str(tuple->protonum));
00231 BUFFER_SIZE(ret, size, len, offset);
00232
00233 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_ORIG);
00234 BUFFER_SIZE(ret, size, len, offset);
00235
00236 ret = __snprintf_proto_xml(buf+offset, len, tuple, __DIR_REPL);
00237 BUFFER_SIZE(ret, size, len, offset);
00238
00239 ret = snprintf(buf+offset, len, "</layer4>");
00240 BUFFER_SIZE(ret, size, len, offset);
00241
00242 if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->set) &&
00243 test_bit(ATTR_ORIG_COUNTER_BYTES, ct->set)) {
00244 ret = snprintf(buf+offset, len, "<counters>");
00245 BUFFER_SIZE(ret, size, len, offset);
00246
00247 ret = __snprintf_counters_xml(buf+offset, len, ct, dir);
00248 BUFFER_SIZE(ret, size, len, offset);
00249
00250 ret = snprintf(buf+offset, len, "</counters>");
00251 BUFFER_SIZE(ret, size, len, offset);
00252 }
00253
00254 ret = snprintf(buf+offset, len, "</meta>");
00255 BUFFER_SIZE(ret, size, len, offset);
00256
00257 return size;
00258 }
00259
00260 int __snprintf_conntrack_xml(char *buf,
00261 unsigned int len,
00262 const struct nf_conntrack *ct,
00263 const unsigned int msg_type,
00264 const unsigned int flags)
00265 {
00266 int ret = 0;
00267 unsigned int size = 0, offset = 0;
00268
00269 switch(msg_type) {
00270 case NFCT_T_NEW:
00271 ret = snprintf(buf, len, "<flow type=\"new\">");
00272 break;
00273 case NFCT_T_UPDATE:
00274 ret = snprintf(buf, len, "<flow type=\"update\">");
00275 break;
00276 case NFCT_T_DESTROY:
00277 ret = snprintf(buf, len, "<flow type=\"destroy\">");
00278 break;
00279 default:
00280 ret = snprintf(buf, len, "<flow>");
00281 break;
00282 }
00283
00284 BUFFER_SIZE(ret, size, len, offset);
00285
00286 ret = __snprintf_tuple_xml(buf+offset, len, ct, __DIR_ORIG);
00287 BUFFER_SIZE(ret, size, len, offset);
00288
00289 ret = __snprintf_tuple_xml(buf+offset, len, ct, __DIR_REPL);
00290 BUFFER_SIZE(ret, size, len, offset);
00291
00292 if (test_bit(ATTR_TCP_STATE, ct->set) ||
00293 test_bit(ATTR_SCTP_STATE, ct->set) ||
00294 test_bit(ATTR_DCCP_STATE, ct->set) ||
00295 test_bit(ATTR_TIMEOUT, ct->set) ||
00296 test_bit(ATTR_MARK, ct->set) ||
00297 test_bit(ATTR_SECMARK, ct->set) ||
00298 test_bit(ATTR_ZONE, ct->set) ||
00299 test_bit(ATTR_USE, ct->set) ||
00300 test_bit(ATTR_STATUS, ct->set) ||
00301 test_bit(ATTR_ID, ct->set)) {
00302 ret = snprintf(buf+offset, len,
00303 "<meta direction=\"independent\">");
00304 BUFFER_SIZE(ret, size, len, offset);
00305 }
00306
00307 if (test_bit(ATTR_TCP_STATE, ct->set)) {
00308 ret = snprintf(buf+offset, len, "<state>%s</state>",
00309 ct->protoinfo.tcp.state < TCP_CONNTRACK_MAX ?
00310 states[ct->protoinfo.tcp.state] :
00311 states[TCP_CONNTRACK_NONE]);
00312 BUFFER_SIZE(ret, size, len, offset);
00313 }
00314
00315 if (test_bit(ATTR_SCTP_STATE, ct->set)) {
00316 ret = snprintf(buf+offset, len, "<state>%s</state>",
00317 ct->protoinfo.sctp.state < SCTP_CONNTRACK_MAX ?
00318 states[ct->protoinfo.sctp.state] :
00319 states[SCTP_CONNTRACK_NONE]);
00320 BUFFER_SIZE(ret, size, len, offset);
00321 }
00322
00323 if (test_bit(ATTR_DCCP_STATE, ct->set)) {
00324 ret = snprintf(buf+offset, len, "<state>%s</state>",
00325 ct->protoinfo.sctp.state < DCCP_CONNTRACK_MAX ?
00326 states[ct->protoinfo.dccp.state] :
00327 states[DCCP_CONNTRACK_NONE]);
00328 BUFFER_SIZE(ret, size, len, offset);
00329 }
00330
00331 if (test_bit(ATTR_TIMEOUT, ct->set)) {
00332 ret = snprintf(buf+offset, len,
00333 "<timeout>%u</timeout>", ct->timeout);
00334 BUFFER_SIZE(ret, size, len, offset);
00335 }
00336
00337 if (test_bit(ATTR_MARK, ct->set)) {
00338 ret = snprintf(buf+offset, len, "<mark>%u</mark>", ct->mark);
00339 BUFFER_SIZE(ret, size, len, offset);
00340 }
00341
00342 if (test_bit(ATTR_SECMARK, ct->set)) {
00343 ret = snprintf(buf+offset, len,
00344 "<secmark>%u</secmark>", ct->secmark);
00345 BUFFER_SIZE(ret, size, len, offset);
00346 }
00347
00348 if (test_bit(ATTR_SECCTX, ct->set)) {
00349 ret = snprintf(buf+offset, len,
00350 "<secctx>%s</secctx>", ct->secctx);
00351 BUFFER_SIZE(ret, size, len, offset);
00352 }
00353
00354 if (test_bit(ATTR_ZONE, ct->set)) {
00355 ret = snprintf(buf+offset, len, "<zone>%u</zone>", ct->zone);
00356 BUFFER_SIZE(ret, size, len, offset);
00357 }
00358
00359 if (test_bit(ATTR_USE, ct->set)) {
00360 ret = snprintf(buf+offset, len, "<use>%u</use>", ct->use);
00361 BUFFER_SIZE(ret, size, len, offset);
00362 }
00363
00364 if (test_bit(ATTR_ID, ct->set)) {
00365 ret = snprintf(buf+offset, len, "<id>%u</id>", ct->id);
00366 BUFFER_SIZE(ret, size, len, offset);
00367 }
00368
00369 if (test_bit(ATTR_STATUS, ct->set)
00370 && ct->status & IPS_ASSURED) {
00371 ret = snprintf(buf+offset, len, "<assured/>");
00372 BUFFER_SIZE(ret, size, len, offset);
00373 }
00374
00375 if (test_bit(ATTR_STATUS, ct->set)
00376 && !(ct->status & IPS_SEEN_REPLY)) {
00377 ret = snprintf(buf+offset, len, "<unreplied/>");
00378 BUFFER_SIZE(ret, size, len, offset);
00379 }
00380
00381 if (test_bit(ATTR_TCP_STATE, ct->set) ||
00382 test_bit(ATTR_SCTP_STATE, ct->set) ||
00383 test_bit(ATTR_DCCP_STATE, ct->set) ||
00384 test_bit(ATTR_TIMEOUT, ct->set) ||
00385 test_bit(ATTR_MARK, ct->set) ||
00386 test_bit(ATTR_SECMARK, ct->set) ||
00387 test_bit(ATTR_ZONE, ct->set) ||
00388 test_bit(ATTR_USE, ct->set) ||
00389 test_bit(ATTR_STATUS, ct->set) ||
00390 test_bit(ATTR_ID, ct->set)) {
00391 ret = snprintf(buf+offset, len, "</meta>");
00392 BUFFER_SIZE(ret, size, len, offset);
00393 }
00394
00395 if (flags & NFCT_OF_TIME) {
00396 time_t t;
00397 struct tm tm;
00398
00399 t = time(NULL);
00400 if (localtime_r(&t, &tm) == NULL)
00401 goto err_out;
00402
00403 ret = snprintf(buf+offset, len, "<when>");
00404 BUFFER_SIZE(ret, size, len, offset);
00405
00406 ret = snprintf(buf+offset, len, "<hour>%d</hour>", tm.tm_hour);
00407 BUFFER_SIZE(ret, size, len, offset);
00408
00409 ret = snprintf(buf+offset, len, "<min>%02d</min>", tm.tm_min);
00410 BUFFER_SIZE(ret, size, len, offset);
00411
00412 ret = snprintf(buf+offset, len, "<sec>%02d</sec>", tm.tm_sec);
00413 BUFFER_SIZE(ret, size, len, offset);
00414
00415 ret = snprintf(buf+offset, len, "<wday>%d</wday>",
00416 tm.tm_wday + 1);
00417 BUFFER_SIZE(ret, size, len, offset);
00418
00419 ret = snprintf(buf+offset, len, "<day>%d</day>", tm.tm_mday);
00420 BUFFER_SIZE(ret, size, len, offset);
00421
00422 ret = snprintf(buf+offset, len, "<month>%d</month>",
00423 tm.tm_mon + 1);
00424 BUFFER_SIZE(ret, size, len, offset);
00425
00426 ret = snprintf(buf+offset, len, "<year>%d</year>",
00427 1900 + tm.tm_year);
00428 BUFFER_SIZE(ret, size, len, offset);
00429
00430 ret = snprintf(buf+offset, len, "</when>");
00431 BUFFER_SIZE(ret, size, len, offset);
00432 }
00433
00434 err_out:
00435 ret = snprintf(buf+offset, len, "</flow>");
00436 BUFFER_SIZE(ret, size, len, offset);
00437
00438 return size;
00439 }