1276761Sdelphij/* 2276761Sdelphij * Copyright (c) 2013, Petar Alilovic, 3276761Sdelphij * Faculty of Electrical Engineering and Computing, University of Zagreb 4276761Sdelphij * All rights reserved 5276761Sdelphij * 6276761Sdelphij * Redistribution and use in source and binary forms, with or without 7276761Sdelphij * modification, are permitted provided that the following conditions are met: 8276761Sdelphij * 9276761Sdelphij * * Redistributions of source code must retain the above copyright notice, 10276761Sdelphij * this list of conditions and the following disclaimer. 11276761Sdelphij * * Redistributions in binary form must reproduce the above copyright 12276761Sdelphij * notice, this list of conditions and the following disclaimer in the 13276761Sdelphij * documentation and/or other materials provided with the distribution. 14276761Sdelphij * 15276761Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 16276761Sdelphij * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17276761Sdelphij * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18276761Sdelphij * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY 19276761Sdelphij * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20276761Sdelphij * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21276761Sdelphij * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22276761Sdelphij * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23276761Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24276761Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 25276761Sdelphij * DAMAGE. 26276761Sdelphij */ 27276761Sdelphij 28313537Sglebius/* \summary: DLT_NFLOG printer */ 29313537Sglebius 30276761Sdelphij#ifdef HAVE_CONFIG_H 31276761Sdelphij#include "config.h" 32276761Sdelphij#endif 33276761Sdelphij 34313537Sglebius#include <netdissect-stdinc.h> 35276761Sdelphij 36313537Sglebius#include "netdissect.h" 37276761Sdelphij 38276761Sdelphij#if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) 39276761Sdelphij#include <pcap/nflog.h> 40276761Sdelphij 41276761Sdelphijstatic const struct tok nflog_values[] = { 42276761Sdelphij { AF_INET, "IPv4" }, 43313537Sglebius#ifdef AF_INET6 44276761Sdelphij { AF_INET6, "IPv6" }, 45313537Sglebius#endif /*AF_INET6*/ 46276761Sdelphij { 0, NULL } 47276761Sdelphij}; 48276761Sdelphij 49276761Sdelphijstatic inline void 50276761Sdelphijnflog_hdr_print(netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length) 51276761Sdelphij{ 52276761Sdelphij ND_PRINT((ndo, "version %d, resource ID %d", hdr->nflog_version, ntohs(hdr->nflog_rid))); 53276761Sdelphij 54276761Sdelphij if (!ndo->ndo_qflag) { 55276761Sdelphij ND_PRINT((ndo,", family %s (%d)", 56276761Sdelphij tok2str(nflog_values, "Unknown", 57276761Sdelphij hdr->nflog_family), 58276761Sdelphij hdr->nflog_family)); 59276761Sdelphij } else { 60276761Sdelphij ND_PRINT((ndo,", %s", 61276761Sdelphij tok2str(nflog_values, 62276761Sdelphij "Unknown NFLOG (0x%02x)", 63276761Sdelphij hdr->nflog_family))); 64276761Sdelphij } 65276761Sdelphij 66276761Sdelphij ND_PRINT((ndo, ", length %u: ", length)); 67276761Sdelphij} 68276761Sdelphij 69276761Sdelphiju_int 70276761Sdelphijnflog_if_print(netdissect_options *ndo, 71276761Sdelphij const struct pcap_pkthdr *h, const u_char *p) 72276761Sdelphij{ 73276761Sdelphij const nflog_hdr_t *hdr = (const nflog_hdr_t *)p; 74276761Sdelphij const nflog_tlv_t *tlv; 75276761Sdelphij uint16_t size; 76276761Sdelphij uint16_t h_size = sizeof(nflog_hdr_t); 77276761Sdelphij u_int caplen = h->caplen; 78276761Sdelphij u_int length = h->len; 79276761Sdelphij 80276761Sdelphij if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) { 81276761Sdelphij ND_PRINT((ndo, "[|nflog]")); 82276761Sdelphij return h_size; 83276761Sdelphij } 84276761Sdelphij 85313537Sglebius if (hdr->nflog_version != 0) { 86276761Sdelphij ND_PRINT((ndo, "version %u (unknown)", hdr->nflog_version)); 87276761Sdelphij return h_size; 88276761Sdelphij } 89276761Sdelphij 90276761Sdelphij if (ndo->ndo_eflag) 91276761Sdelphij nflog_hdr_print(ndo, hdr, length); 92276761Sdelphij 93276761Sdelphij p += sizeof(nflog_hdr_t); 94276761Sdelphij length -= sizeof(nflog_hdr_t); 95276761Sdelphij caplen -= sizeof(nflog_hdr_t); 96276761Sdelphij 97276761Sdelphij while (length > 0) { 98276761Sdelphij /* We have some data. Do we have enough for the TLV header? */ 99276761Sdelphij if (caplen < sizeof(nflog_tlv_t) || length < sizeof(nflog_tlv_t)) { 100276761Sdelphij /* No. */ 101276761Sdelphij ND_PRINT((ndo, "[|nflog]")); 102276761Sdelphij return h_size; 103276761Sdelphij } 104276761Sdelphij 105276761Sdelphij tlv = (const nflog_tlv_t *) p; 106276761Sdelphij size = tlv->tlv_length; 107276761Sdelphij if (size % 4 != 0) 108276761Sdelphij size += 4 - size % 4; 109276761Sdelphij 110276761Sdelphij /* Is the TLV's length less than the minimum? */ 111276761Sdelphij if (size < sizeof(nflog_tlv_t)) { 112276761Sdelphij /* Yes. Give up now. */ 113276761Sdelphij ND_PRINT((ndo, "[|nflog]")); 114276761Sdelphij return h_size; 115276761Sdelphij } 116276761Sdelphij 117276761Sdelphij /* Do we have enough data for the full TLV? */ 118276761Sdelphij if (caplen < size || length < size) { 119276761Sdelphij /* No. */ 120276761Sdelphij ND_PRINT((ndo, "[|nflog]")); 121276761Sdelphij return h_size; 122276761Sdelphij } 123276761Sdelphij 124276761Sdelphij if (tlv->tlv_type == NFULA_PAYLOAD) { 125276761Sdelphij /* 126276761Sdelphij * This TLV's data is the packet payload. 127276761Sdelphij * Skip past the TLV header, and break out 128276761Sdelphij * of the loop so we print the packet data. 129276761Sdelphij */ 130276761Sdelphij p += sizeof(nflog_tlv_t); 131276761Sdelphij h_size += sizeof(nflog_tlv_t); 132276761Sdelphij length -= sizeof(nflog_tlv_t); 133276761Sdelphij caplen -= sizeof(nflog_tlv_t); 134276761Sdelphij break; 135276761Sdelphij } 136276761Sdelphij 137276761Sdelphij p += size; 138276761Sdelphij h_size += size; 139276761Sdelphij length -= size; 140276761Sdelphij caplen -= size; 141276761Sdelphij } 142276761Sdelphij 143276761Sdelphij switch (hdr->nflog_family) { 144276761Sdelphij 145276761Sdelphij case AF_INET: 146276761Sdelphij ip_print(ndo, p, length); 147276761Sdelphij break; 148276761Sdelphij 149285275Spkelsey#ifdef AF_INET6 150276761Sdelphij case AF_INET6: 151276761Sdelphij ip6_print(ndo, p, length); 152276761Sdelphij break; 153285275Spkelsey#endif /* AF_INET6 */ 154276761Sdelphij 155276761Sdelphij default: 156276761Sdelphij if (!ndo->ndo_eflag) 157276761Sdelphij nflog_hdr_print(ndo, hdr, 158276761Sdelphij length + sizeof(nflog_hdr_t)); 159276761Sdelphij 160276761Sdelphij if (!ndo->ndo_suppress_default_print) 161276761Sdelphij ND_DEFAULTPRINT(p, caplen); 162276761Sdelphij break; 163276761Sdelphij } 164276761Sdelphij 165276761Sdelphij return h_size; 166276761Sdelphij} 167276761Sdelphij 168276761Sdelphij#endif /* defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) */ 169