13c602fabSXin LI /* 23c602fabSXin LI * Copyright (c) 2013, Petar Alilovic, 33c602fabSXin LI * Faculty of Electrical Engineering and Computing, University of Zagreb 43c602fabSXin LI * All rights reserved 53c602fabSXin LI * 63c602fabSXin LI * Redistribution and use in source and binary forms, with or without 73c602fabSXin LI * modification, are permitted provided that the following conditions are met: 83c602fabSXin LI * 93c602fabSXin LI * * Redistributions of source code must retain the above copyright notice, 103c602fabSXin LI * this list of conditions and the following disclaimer. 113c602fabSXin LI * * Redistributions in binary form must reproduce the above copyright 123c602fabSXin LI * notice, this list of conditions and the following disclaimer in the 133c602fabSXin LI * documentation and/or other materials provided with the distribution. 143c602fabSXin LI * 153c602fabSXin LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 163c602fabSXin LI * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 173c602fabSXin LI * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 183c602fabSXin LI * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY 193c602fabSXin LI * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 203c602fabSXin LI * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 213c602fabSXin LI * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 223c602fabSXin LI * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 233c602fabSXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 243c602fabSXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 253c602fabSXin LI * DAMAGE. 263c602fabSXin LI */ 273c602fabSXin LI 283340d773SGleb Smirnoff /* \summary: DLT_NFLOG printer */ 293340d773SGleb Smirnoff 303c602fabSXin LI #ifdef HAVE_CONFIG_H 31*ee67461eSJoseph Mingrone #include <config.h> 323c602fabSXin LI #endif 333c602fabSXin LI 34*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 353c602fabSXin LI 363340d773SGleb Smirnoff #include "netdissect.h" 37*ee67461eSJoseph Mingrone #include "extract.h" 383c602fabSXin LI 39*ee67461eSJoseph Mingrone #ifdef DLT_NFLOG 40*ee67461eSJoseph Mingrone 41*ee67461eSJoseph Mingrone /* 42*ee67461eSJoseph Mingrone * Structure of an NFLOG header and TLV parts, as described at 43*ee67461eSJoseph Mingrone * https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html 44*ee67461eSJoseph Mingrone * 45*ee67461eSJoseph Mingrone * The NFLOG header is big-endian. 46*ee67461eSJoseph Mingrone * 47*ee67461eSJoseph Mingrone * The TLV length and type are in host byte order. The value is either 48*ee67461eSJoseph Mingrone * big-endian or is an array of bytes in some externally-specified byte 49*ee67461eSJoseph Mingrone * order (text string, link-layer address, link-layer header, packet 50*ee67461eSJoseph Mingrone * data, etc.). 51*ee67461eSJoseph Mingrone */ 52*ee67461eSJoseph Mingrone typedef struct nflog_hdr { 53*ee67461eSJoseph Mingrone nd_uint8_t nflog_family; /* address family */ 54*ee67461eSJoseph Mingrone nd_uint8_t nflog_version; /* version */ 55*ee67461eSJoseph Mingrone nd_uint16_t nflog_rid; /* resource ID */ 56*ee67461eSJoseph Mingrone } nflog_hdr_t; 57*ee67461eSJoseph Mingrone 58*ee67461eSJoseph Mingrone #define NFLOG_HDR_LEN sizeof(nflog_hdr_t) 59*ee67461eSJoseph Mingrone 60*ee67461eSJoseph Mingrone typedef struct nflog_tlv { 61*ee67461eSJoseph Mingrone nd_uint16_t tlv_length; /* tlv length */ 62*ee67461eSJoseph Mingrone nd_uint16_t tlv_type; /* tlv type */ 63*ee67461eSJoseph Mingrone /* value follows this */ 64*ee67461eSJoseph Mingrone } nflog_tlv_t; 65*ee67461eSJoseph Mingrone 66*ee67461eSJoseph Mingrone #define NFLOG_TLV_LEN sizeof(nflog_tlv_t) 67*ee67461eSJoseph Mingrone 68*ee67461eSJoseph Mingrone typedef struct nflog_packet_hdr { 69*ee67461eSJoseph Mingrone nd_uint16_t hw_protocol; /* hw protocol */ 70*ee67461eSJoseph Mingrone nd_uint8_t hook; /* netfilter hook */ 71*ee67461eSJoseph Mingrone nd_byte pad[1]; /* padding to 32 bits */ 72*ee67461eSJoseph Mingrone } nflog_packet_hdr_t; 73*ee67461eSJoseph Mingrone 74*ee67461eSJoseph Mingrone typedef struct nflog_hwaddr { 75*ee67461eSJoseph Mingrone nd_uint16_t hw_addrlen; /* address length */ 76*ee67461eSJoseph Mingrone nd_byte pad[2]; /* padding to 32-bit boundary */ 77*ee67461eSJoseph Mingrone nd_byte hw_addr[8]; /* address, up to 8 bytes */ 78*ee67461eSJoseph Mingrone } nflog_hwaddr_t; 79*ee67461eSJoseph Mingrone 80*ee67461eSJoseph Mingrone typedef struct nflog_timestamp { 81*ee67461eSJoseph Mingrone nd_uint64_t sec; 82*ee67461eSJoseph Mingrone nd_uint64_t usec; 83*ee67461eSJoseph Mingrone } nflog_timestamp_t; 84*ee67461eSJoseph Mingrone 85*ee67461eSJoseph Mingrone /* 86*ee67461eSJoseph Mingrone * TLV types. 87*ee67461eSJoseph Mingrone */ 88*ee67461eSJoseph Mingrone #define NFULA_PACKET_HDR 1 /* nflog_packet_hdr_t */ 89*ee67461eSJoseph Mingrone #define NFULA_MARK 2 /* packet mark from skbuff */ 90*ee67461eSJoseph Mingrone #define NFULA_TIMESTAMP 3 /* nflog_timestamp_t for skbuff's time stamp */ 91*ee67461eSJoseph Mingrone #define NFULA_IFINDEX_INDEV 4 /* ifindex of device on which packet received (possibly bridge group) */ 92*ee67461eSJoseph Mingrone #define NFULA_IFINDEX_OUTDEV 5 /* ifindex of device on which packet transmitted (possibly bridge group) */ 93*ee67461eSJoseph Mingrone #define NFULA_IFINDEX_PHYSINDEV 6 /* ifindex of physical device on which packet received (not bridge group) */ 94*ee67461eSJoseph Mingrone #define NFULA_IFINDEX_PHYSOUTDEV 7 /* ifindex of physical device on which packet transmitted (not bridge group) */ 95*ee67461eSJoseph Mingrone #define NFULA_HWADDR 8 /* nflog_hwaddr_t for hardware address */ 96*ee67461eSJoseph Mingrone #define NFULA_PAYLOAD 9 /* packet payload */ 97*ee67461eSJoseph Mingrone #define NFULA_PREFIX 10 /* text string - null-terminated, count includes NUL */ 98*ee67461eSJoseph Mingrone #define NFULA_UID 11 /* UID owning socket on which packet was sent/received */ 99*ee67461eSJoseph Mingrone #define NFULA_SEQ 12 /* sequence number of packets on this NFLOG socket */ 100*ee67461eSJoseph Mingrone #define NFULA_SEQ_GLOBAL 13 /* sequence number of pakets on all NFLOG sockets */ 101*ee67461eSJoseph Mingrone #define NFULA_GID 14 /* GID owning socket on which packet was sent/received */ 102*ee67461eSJoseph Mingrone #define NFULA_HWTYPE 15 /* ARPHRD_ type of skbuff's device */ 103*ee67461eSJoseph Mingrone #define NFULA_HWHEADER 16 /* skbuff's MAC-layer header */ 104*ee67461eSJoseph Mingrone #define NFULA_HWLEN 17 /* length of skbuff's MAC-layer header */ 1053c602fabSXin LI 1063c602fabSXin LI static const struct tok nflog_values[] = { 1073c602fabSXin LI { AF_INET, "IPv4" }, 1083c602fabSXin LI { AF_INET6, "IPv6" }, 1093c602fabSXin LI { 0, NULL } 1103c602fabSXin LI }; 1113c602fabSXin LI 112*ee67461eSJoseph Mingrone static void 1133c602fabSXin LI nflog_hdr_print(netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length) 1143c602fabSXin LI { 115*ee67461eSJoseph Mingrone ND_PRINT("version %u, resource ID %u", 116*ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_version), GET_BE_U_2(hdr->nflog_rid)); 1173c602fabSXin LI 1183c602fabSXin LI if (!ndo->ndo_qflag) { 119*ee67461eSJoseph Mingrone ND_PRINT(", family %s (%u)", 1203c602fabSXin LI tok2str(nflog_values, "Unknown", 121*ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_family)), 122*ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_family)); 1233c602fabSXin LI } else { 124*ee67461eSJoseph Mingrone ND_PRINT(", %s", 1253c602fabSXin LI tok2str(nflog_values, 1263c602fabSXin LI "Unknown NFLOG (0x%02x)", 127*ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_family))); 1283c602fabSXin LI } 1293c602fabSXin LI 130*ee67461eSJoseph Mingrone ND_PRINT(", length %u: ", length); 1313c602fabSXin LI } 1323c602fabSXin LI 133*ee67461eSJoseph Mingrone void 1343c602fabSXin LI nflog_if_print(netdissect_options *ndo, 1353c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p) 1363c602fabSXin LI { 1373c602fabSXin LI const nflog_hdr_t *hdr = (const nflog_hdr_t *)p; 1383c602fabSXin LI uint16_t size; 139*ee67461eSJoseph Mingrone uint16_t h_size = NFLOG_HDR_LEN; 1403c602fabSXin LI u_int caplen = h->caplen; 1413c602fabSXin LI u_int length = h->len; 1423c602fabSXin LI 143*ee67461eSJoseph Mingrone ndo->ndo_protocol = "nflog"; 144*ee67461eSJoseph Mingrone if (caplen < NFLOG_HDR_LEN) { 145*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 146*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen; 147*ee67461eSJoseph Mingrone return; 1483c602fabSXin LI } 149*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += NFLOG_HDR_LEN; 1503c602fabSXin LI 151*ee67461eSJoseph Mingrone ND_TCHECK_SIZE(hdr); 152*ee67461eSJoseph Mingrone if (GET_U_1(hdr->nflog_version) != 0) { 153*ee67461eSJoseph Mingrone ND_PRINT("version %u (unknown)", GET_U_1(hdr->nflog_version)); 154*ee67461eSJoseph Mingrone return; 1553c602fabSXin LI } 1563c602fabSXin LI 1573c602fabSXin LI if (ndo->ndo_eflag) 1583c602fabSXin LI nflog_hdr_print(ndo, hdr, length); 1593c602fabSXin LI 160*ee67461eSJoseph Mingrone p += NFLOG_HDR_LEN; 161*ee67461eSJoseph Mingrone length -= NFLOG_HDR_LEN; 162*ee67461eSJoseph Mingrone caplen -= NFLOG_HDR_LEN; 1633c602fabSXin LI 1643c602fabSXin LI while (length > 0) { 165*ee67461eSJoseph Mingrone const nflog_tlv_t *tlv; 166*ee67461eSJoseph Mingrone 1673c602fabSXin LI /* We have some data. Do we have enough for the TLV header? */ 168*ee67461eSJoseph Mingrone if (caplen < NFLOG_TLV_LEN) 169*ee67461eSJoseph Mingrone goto trunc; /* No. */ 1703c602fabSXin LI 1713c602fabSXin LI tlv = (const nflog_tlv_t *) p; 172*ee67461eSJoseph Mingrone ND_TCHECK_SIZE(tlv); 173*ee67461eSJoseph Mingrone size = GET_HE_U_2(tlv->tlv_length); 1743c602fabSXin LI if (size % 4 != 0) 1753c602fabSXin LI size += 4 - size % 4; 1763c602fabSXin LI 1773c602fabSXin LI /* Is the TLV's length less than the minimum? */ 178*ee67461eSJoseph Mingrone if (size < NFLOG_TLV_LEN) 179*ee67461eSJoseph Mingrone goto trunc; /* Yes. Give up now. */ 1803c602fabSXin LI 1813c602fabSXin LI /* Do we have enough data for the full TLV? */ 182*ee67461eSJoseph Mingrone if (caplen < size) 183*ee67461eSJoseph Mingrone goto trunc; /* No. */ 1843c602fabSXin LI 185*ee67461eSJoseph Mingrone if (GET_HE_U_2(tlv->tlv_type) == NFULA_PAYLOAD) { 1863c602fabSXin LI /* 1873c602fabSXin LI * This TLV's data is the packet payload. 1883c602fabSXin LI * Skip past the TLV header, and break out 1893c602fabSXin LI * of the loop so we print the packet data. 1903c602fabSXin LI */ 191*ee67461eSJoseph Mingrone p += NFLOG_TLV_LEN; 192*ee67461eSJoseph Mingrone h_size += NFLOG_TLV_LEN; 193*ee67461eSJoseph Mingrone length -= NFLOG_TLV_LEN; 194*ee67461eSJoseph Mingrone caplen -= NFLOG_TLV_LEN; 1953c602fabSXin LI break; 1963c602fabSXin LI } 1973c602fabSXin LI 1983c602fabSXin LI p += size; 1993c602fabSXin LI h_size += size; 2003c602fabSXin LI length -= size; 2013c602fabSXin LI caplen -= size; 2023c602fabSXin LI } 2033c602fabSXin LI 204*ee67461eSJoseph Mingrone switch (GET_U_1(hdr->nflog_family)) { 2053c602fabSXin LI 2063c602fabSXin LI case AF_INET: 2073c602fabSXin LI ip_print(ndo, p, length); 2083c602fabSXin LI break; 2093c602fabSXin LI 2103c602fabSXin LI case AF_INET6: 2113c602fabSXin LI ip6_print(ndo, p, length); 2123c602fabSXin LI break; 2133c602fabSXin LI 2143c602fabSXin LI default: 2153c602fabSXin LI if (!ndo->ndo_eflag) 2163c602fabSXin LI nflog_hdr_print(ndo, hdr, 217*ee67461eSJoseph Mingrone length + NFLOG_HDR_LEN); 2183c602fabSXin LI 2193c602fabSXin LI if (!ndo->ndo_suppress_default_print) 2203c602fabSXin LI ND_DEFAULTPRINT(p, caplen); 2213c602fabSXin LI break; 2223c602fabSXin LI } 2233c602fabSXin LI 224*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += h_size - NFLOG_HDR_LEN; 225*ee67461eSJoseph Mingrone return; 226*ee67461eSJoseph Mingrone trunc: 227*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 228*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += h_size - NFLOG_HDR_LEN; 2293c602fabSXin LI } 2303c602fabSXin LI 231*ee67461eSJoseph Mingrone #endif /* DLT_NFLOG */ 232