• Main Page
  • Modules
  • Data Structures
  • Files
  • File List

snprintf_xml.c

00001 /*
00002  * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
00003  *
00004  * This software may be used and distributed according to the terms
00005  * of the GNU General Public License, incorporated herein by reference.
00006  */
00007 
00008 #include "internal/internal.h"
00009 
00010 /*
00011  * XML output sample:
00012  *
00013  * <flow>
00014  *      <meta direction="original">
00015  *              <layer3 protonum="2" protoname="IPv4">
00016  *                      <src>192.168.0.1</src>
00017  *                      <dst>192.168.0.2</dst>
00018  *              </layer3>
00019  *              <layer4 protonum="16" protoname"udp">
00020  *                      <sport>80</sport>
00021  *                      <dport>56665</dport>
00022  *              </layer4>
00023  *              <counters>
00024  *                      <bytes>10</bytes>
00025  *                      <packets>1</packets>
00026  *              </counters>
00027  *      </meta>
00028  *      <meta direction="reply">
00029  *              <layer3 protonum="2" protoname="IPv4">
00030  *                      <src>192.168.0.2</src>
00031  *                      <dst>192.168.0.1</dst>
00032  *              </layer3>
00033  *              <layer4 protonum="16" protoname="udp">
00034  *                      <sport>80</sport>
00035  *                      <dport>56665</dport>
00036  *              </layer4>
00037  *              <counters>
00038  *                      <bytes>5029</bytes>
00039  *                      <packets>12</packets>
00040  *              </counters>
00041  *      </meta>
00042  *      <meta direction="independent">
00043  *              <state>ESTABLISHED</state>
00044  *              <timeout>100</timeout>
00045  *              <mark>1</mark>
00046  *              <secmark>0</secmark>
00047  *              <id>453281439</id>
00048  *              <use>1</use>
00049  *              <assured/>
00050  *      </meta>
00051  * </flow>
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 }

Generated on Wed Jan 26 2011 23:11:37 for libnetfilter_conntrack by  doxygen 1.7.1