X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/a6e30f1195eaf56cc88ae4c3fad0225d49d135f1..486704db7c840dcfb51f70f1812d9c3ad37ad39c:/print-nflog.c diff --git a/print-nflog.c b/print-nflog.c index eed9c484..a29b930c 100644 --- a/print-nflog.c +++ b/print-nflog.c @@ -1,36 +1,166 @@ +/* + * Copyright (c) 2013, Petar Alilovic, + * Faculty of Electrical Engineering and Computing, University of Zagreb + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif #include -#include -#include - -#include "netdissect.h" #include "interface.h" -#ifdef DLT_NFLOG +#if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) +#include + +static const struct tok nflog_values[] = { + { AF_INET, "IPv4" }, +#ifdef INET6 + { AF_INET6, "IPv6" }, +#endif /*INET6*/ + { 0, NULL } +}; -static void -nflog_print(struct netdissect_options *ndo, const u_char *p, u_int length, u_int caplen _U_) +static inline void +nflog_hdr_print(netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length) { - ip_print(ndo, p, length); - return; + ND_PRINT((ndo, "version %d, resource ID %d", hdr->nflog_version, ntohs(hdr->nflog_rid))); + + if (!ndo->ndo_qflag) { + ND_PRINT((ndo,", family %s (%d)", + tok2str(nflog_values, "Unknown", + hdr->nflog_family), + hdr->nflog_family)); + } else { + ND_PRINT((ndo,", %s", + tok2str(nflog_values, + "Unknown NFLOG (0x%02x)", + hdr->nflog_family))); + } + + ND_PRINT((ndo, ", length %u: ", length)); } u_int -nflog_if_print(struct netdissect_options *ndo, - const struct pcap_pkthdr *h, const u_char *p) +nflog_if_print(netdissect_options *ndo, + const struct pcap_pkthdr *h, const u_char *p) { - if (h->len < 104 || h->caplen < 104) { - ND_PRINT((ndo, "[!nflog]")); - return h->caplen; + const nflog_hdr_t *hdr = (const nflog_hdr_t *)p; + const nflog_tlv_t *tlv; + uint16_t size; + uint16_t h_size = sizeof(nflog_hdr_t); + u_int caplen = h->caplen; + u_int length = h->len; + + if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) { + ND_PRINT((ndo, "[|nflog]")); + return h_size; + } + + if (!(hdr->nflog_version) == 0) { + ND_PRINT((ndo, "version %u (unknown)", hdr->nflog_version)); + return h_size; + } + + if (ndo->ndo_eflag) + nflog_hdr_print(ndo, hdr, length); + + p += sizeof(nflog_hdr_t); + length -= sizeof(nflog_hdr_t); + caplen -= sizeof(nflog_hdr_t); + + while (length > 0) { + /* We have some data. Do we have enough for the TLV header? */ + if (caplen < sizeof(nflog_tlv_t) || length < sizeof(nflog_tlv_t)) { + /* No. */ + ND_PRINT((ndo, "[|nflog]")); + return h_size; + } + + tlv = (const nflog_tlv_t *) p; + size = tlv->tlv_length; + if (size % 4 != 0) + size += 4 - size % 4; + + /* Is the TLV's length less than the minimum? */ + if (size < sizeof(nflog_tlv_t)) { + /* Yes. Give up now. */ + ND_PRINT((ndo, "[|nflog]")); + return h_size; + } + + /* Do we have enough data for the full TLV? */ + if (caplen < size || length < size) { + /* No. */ + ND_PRINT((ndo, "[|nflog]")); + return h_size; + } + + if (tlv->tlv_type == NFULA_PAYLOAD) { + /* + * This TLV's data is the packet payload. + * Skip past the TLV header, and break out + * of the loop so we print the packet data. + */ + p += sizeof(nflog_tlv_t); + h_size += sizeof(nflog_tlv_t); + length -= sizeof(nflog_tlv_t); + caplen -= sizeof(nflog_tlv_t); + break; + } + + p += size; + h_size += size; + length -= size; + caplen -= size; } - nflog_print(ndo, p + 104, h->len - 104, h->caplen - 104); + switch (hdr->nflog_family) { + + case AF_INET: + ip_print(ndo, p, length); + break; + +#ifdef AF_INET6 + case AF_INET6: + ip6_print(ndo, p, length); + break; +#endif /* AF_INET6 */ + + default: + if (!ndo->ndo_eflag) + nflog_hdr_print(ndo, hdr, + length + sizeof(nflog_hdr_t)); + + if (!ndo->ndo_suppress_default_print) + ND_DEFAULTPRINT(p, caplen); + break; + } - return 104; + return h_size; } -#endif /* DLT_NFLOG */ +#endif /* defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) */