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 30ee67461eSJoseph Mingrone #include <config.h> 313c602fabSXin LI 32ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 333c602fabSXin LI 343340d773SGleb Smirnoff #include "netdissect.h" 35ee67461eSJoseph Mingrone #include "extract.h" 363c602fabSXin LI 37ee67461eSJoseph Mingrone #ifdef DLT_NFLOG 38ee67461eSJoseph Mingrone 39ee67461eSJoseph Mingrone /* 40ee67461eSJoseph Mingrone * Structure of an NFLOG header and TLV parts, as described at 41ee67461eSJoseph Mingrone * https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html 42ee67461eSJoseph Mingrone * 43ee67461eSJoseph Mingrone * The NFLOG header is big-endian. 44ee67461eSJoseph Mingrone * 45ee67461eSJoseph Mingrone * The TLV length and type are in host byte order. The value is either 46ee67461eSJoseph Mingrone * big-endian or is an array of bytes in some externally-specified byte 47ee67461eSJoseph Mingrone * order (text string, link-layer address, link-layer header, packet 48ee67461eSJoseph Mingrone * data, etc.). 49ee67461eSJoseph Mingrone */ 50ee67461eSJoseph Mingrone typedef struct nflog_hdr { 51ee67461eSJoseph Mingrone nd_uint8_t nflog_family; /* address family */ 52ee67461eSJoseph Mingrone nd_uint8_t nflog_version; /* version */ 53ee67461eSJoseph Mingrone nd_uint16_t nflog_rid; /* resource ID */ 54ee67461eSJoseph Mingrone } nflog_hdr_t; 55ee67461eSJoseph Mingrone 56ee67461eSJoseph Mingrone #define NFLOG_HDR_LEN sizeof(nflog_hdr_t) 57ee67461eSJoseph Mingrone 58ee67461eSJoseph Mingrone typedef struct nflog_tlv { 59ee67461eSJoseph Mingrone nd_uint16_t tlv_length; /* tlv length */ 60ee67461eSJoseph Mingrone nd_uint16_t tlv_type; /* tlv type */ 61ee67461eSJoseph Mingrone /* value follows this */ 62ee67461eSJoseph Mingrone } nflog_tlv_t; 63ee67461eSJoseph Mingrone 64ee67461eSJoseph Mingrone #define NFLOG_TLV_LEN sizeof(nflog_tlv_t) 65ee67461eSJoseph Mingrone 66ee67461eSJoseph Mingrone typedef struct nflog_packet_hdr { 67ee67461eSJoseph Mingrone nd_uint16_t hw_protocol; /* hw protocol */ 68ee67461eSJoseph Mingrone nd_uint8_t hook; /* netfilter hook */ 69ee67461eSJoseph Mingrone nd_byte pad[1]; /* padding to 32 bits */ 70ee67461eSJoseph Mingrone } nflog_packet_hdr_t; 71ee67461eSJoseph Mingrone 72ee67461eSJoseph Mingrone typedef struct nflog_hwaddr { 73ee67461eSJoseph Mingrone nd_uint16_t hw_addrlen; /* address length */ 74ee67461eSJoseph Mingrone nd_byte pad[2]; /* padding to 32-bit boundary */ 75ee67461eSJoseph Mingrone nd_byte hw_addr[8]; /* address, up to 8 bytes */ 76ee67461eSJoseph Mingrone } nflog_hwaddr_t; 77ee67461eSJoseph Mingrone 78ee67461eSJoseph Mingrone typedef struct nflog_timestamp { 79ee67461eSJoseph Mingrone nd_uint64_t sec; 80ee67461eSJoseph Mingrone nd_uint64_t usec; 81ee67461eSJoseph Mingrone } nflog_timestamp_t; 82ee67461eSJoseph Mingrone 83ee67461eSJoseph Mingrone /* 84ee67461eSJoseph Mingrone * TLV types. 85ee67461eSJoseph Mingrone */ 86ee67461eSJoseph Mingrone #define NFULA_PACKET_HDR 1 /* nflog_packet_hdr_t */ 87ee67461eSJoseph Mingrone #define NFULA_MARK 2 /* packet mark from skbuff */ 88ee67461eSJoseph Mingrone #define NFULA_TIMESTAMP 3 /* nflog_timestamp_t for skbuff's time stamp */ 89ee67461eSJoseph Mingrone #define NFULA_IFINDEX_INDEV 4 /* ifindex of device on which packet received (possibly bridge group) */ 90ee67461eSJoseph Mingrone #define NFULA_IFINDEX_OUTDEV 5 /* ifindex of device on which packet transmitted (possibly bridge group) */ 91ee67461eSJoseph Mingrone #define NFULA_IFINDEX_PHYSINDEV 6 /* ifindex of physical device on which packet received (not bridge group) */ 92ee67461eSJoseph Mingrone #define NFULA_IFINDEX_PHYSOUTDEV 7 /* ifindex of physical device on which packet transmitted (not bridge group) */ 93ee67461eSJoseph Mingrone #define NFULA_HWADDR 8 /* nflog_hwaddr_t for hardware address */ 94ee67461eSJoseph Mingrone #define NFULA_PAYLOAD 9 /* packet payload */ 95ee67461eSJoseph Mingrone #define NFULA_PREFIX 10 /* text string - null-terminated, count includes NUL */ 96ee67461eSJoseph Mingrone #define NFULA_UID 11 /* UID owning socket on which packet was sent/received */ 97ee67461eSJoseph Mingrone #define NFULA_SEQ 12 /* sequence number of packets on this NFLOG socket */ 98*0a7e5f1fSJoseph Mingrone #define NFULA_SEQ_GLOBAL 13 /* sequence number of packets on all NFLOG sockets */ 99ee67461eSJoseph Mingrone #define NFULA_GID 14 /* GID owning socket on which packet was sent/received */ 100ee67461eSJoseph Mingrone #define NFULA_HWTYPE 15 /* ARPHRD_ type of skbuff's device */ 101ee67461eSJoseph Mingrone #define NFULA_HWHEADER 16 /* skbuff's MAC-layer header */ 102ee67461eSJoseph Mingrone #define NFULA_HWLEN 17 /* length of skbuff's MAC-layer header */ 1033c602fabSXin LI 104*0a7e5f1fSJoseph Mingrone /* 105*0a7e5f1fSJoseph Mingrone * Define two constants specifically for the two AF code points from the 106*0a7e5f1fSJoseph Mingrone * LINKTYPE_NFLOG specification above and use these constants instead of 107*0a7e5f1fSJoseph Mingrone * AF_INET and AF_INET6. This is the only way to dissect the "wire" encoding 108*0a7e5f1fSJoseph Mingrone * correctly because some BSD systems define AF_INET6 differently from Linux 109*0a7e5f1fSJoseph Mingrone * (see af.h) and Haiku defines both AF_INET and AF_INET6 differently from 110*0a7e5f1fSJoseph Mingrone * Linux. 111*0a7e5f1fSJoseph Mingrone */ 112*0a7e5f1fSJoseph Mingrone #define NFLOG_AF_INET 2 113*0a7e5f1fSJoseph Mingrone #define NFLOG_AF_INET6 10 1143c602fabSXin LI static const struct tok nflog_values[] = { 115*0a7e5f1fSJoseph Mingrone { NFLOG_AF_INET, "IPv4" }, 116*0a7e5f1fSJoseph Mingrone { NFLOG_AF_INET6, "IPv6" }, 1173c602fabSXin LI { 0, NULL } 1183c602fabSXin LI }; 1193c602fabSXin LI 120ee67461eSJoseph Mingrone static void 1213c602fabSXin LI nflog_hdr_print(netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length) 1223c602fabSXin LI { 123ee67461eSJoseph Mingrone ND_PRINT("version %u, resource ID %u", 124ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_version), GET_BE_U_2(hdr->nflog_rid)); 1253c602fabSXin LI 1263c602fabSXin LI if (!ndo->ndo_qflag) { 127ee67461eSJoseph Mingrone ND_PRINT(", family %s (%u)", 1283c602fabSXin LI tok2str(nflog_values, "Unknown", 129ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_family)), 130ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_family)); 1313c602fabSXin LI } else { 132ee67461eSJoseph Mingrone ND_PRINT(", %s", 1333c602fabSXin LI tok2str(nflog_values, 1343c602fabSXin LI "Unknown NFLOG (0x%02x)", 135ee67461eSJoseph Mingrone GET_U_1(hdr->nflog_family))); 1363c602fabSXin LI } 1373c602fabSXin LI 138ee67461eSJoseph Mingrone ND_PRINT(", length %u: ", length); 1393c602fabSXin LI } 1403c602fabSXin LI 141ee67461eSJoseph Mingrone void 1423c602fabSXin LI nflog_if_print(netdissect_options *ndo, 1433c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p) 1443c602fabSXin LI { 1453c602fabSXin LI const nflog_hdr_t *hdr = (const nflog_hdr_t *)p; 1463c602fabSXin LI uint16_t size; 147ee67461eSJoseph Mingrone uint16_t h_size = NFLOG_HDR_LEN; 1483c602fabSXin LI u_int caplen = h->caplen; 1493c602fabSXin LI u_int length = h->len; 1503c602fabSXin LI 151ee67461eSJoseph Mingrone ndo->ndo_protocol = "nflog"; 152ee67461eSJoseph Mingrone if (caplen < NFLOG_HDR_LEN) { 153ee67461eSJoseph Mingrone nd_print_trunc(ndo); 154ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen; 155ee67461eSJoseph Mingrone return; 1563c602fabSXin LI } 157ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += NFLOG_HDR_LEN; 1583c602fabSXin LI 159ee67461eSJoseph Mingrone ND_TCHECK_SIZE(hdr); 160ee67461eSJoseph Mingrone if (GET_U_1(hdr->nflog_version) != 0) { 161ee67461eSJoseph Mingrone ND_PRINT("version %u (unknown)", GET_U_1(hdr->nflog_version)); 162ee67461eSJoseph Mingrone return; 1633c602fabSXin LI } 1643c602fabSXin LI 1653c602fabSXin LI if (ndo->ndo_eflag) 1663c602fabSXin LI nflog_hdr_print(ndo, hdr, length); 1673c602fabSXin LI 168ee67461eSJoseph Mingrone p += NFLOG_HDR_LEN; 169ee67461eSJoseph Mingrone length -= NFLOG_HDR_LEN; 170ee67461eSJoseph Mingrone caplen -= NFLOG_HDR_LEN; 1713c602fabSXin LI 1723c602fabSXin LI while (length > 0) { 173ee67461eSJoseph Mingrone const nflog_tlv_t *tlv; 174ee67461eSJoseph Mingrone 1753c602fabSXin LI /* We have some data. Do we have enough for the TLV header? */ 176ee67461eSJoseph Mingrone if (caplen < NFLOG_TLV_LEN) 177ee67461eSJoseph Mingrone goto trunc; /* No. */ 1783c602fabSXin LI 1793c602fabSXin LI tlv = (const nflog_tlv_t *) p; 180ee67461eSJoseph Mingrone ND_TCHECK_SIZE(tlv); 181ee67461eSJoseph Mingrone size = GET_HE_U_2(tlv->tlv_length); 1823c602fabSXin LI if (size % 4 != 0) 1833c602fabSXin LI size += 4 - size % 4; 1843c602fabSXin LI 1853c602fabSXin LI /* Is the TLV's length less than the minimum? */ 186ee67461eSJoseph Mingrone if (size < NFLOG_TLV_LEN) 187ee67461eSJoseph Mingrone goto trunc; /* Yes. Give up now. */ 1883c602fabSXin LI 1893c602fabSXin LI /* Do we have enough data for the full TLV? */ 190ee67461eSJoseph Mingrone if (caplen < size) 191ee67461eSJoseph Mingrone goto trunc; /* No. */ 1923c602fabSXin LI 193ee67461eSJoseph Mingrone if (GET_HE_U_2(tlv->tlv_type) == NFULA_PAYLOAD) { 1943c602fabSXin LI /* 1953c602fabSXin LI * This TLV's data is the packet payload. 1963c602fabSXin LI * Skip past the TLV header, and break out 1973c602fabSXin LI * of the loop so we print the packet data. 1983c602fabSXin LI */ 199ee67461eSJoseph Mingrone p += NFLOG_TLV_LEN; 200ee67461eSJoseph Mingrone h_size += NFLOG_TLV_LEN; 201ee67461eSJoseph Mingrone length -= NFLOG_TLV_LEN; 202ee67461eSJoseph Mingrone caplen -= NFLOG_TLV_LEN; 2033c602fabSXin LI break; 2043c602fabSXin LI } 2053c602fabSXin LI 2063c602fabSXin LI p += size; 2073c602fabSXin LI h_size += size; 2083c602fabSXin LI length -= size; 2093c602fabSXin LI caplen -= size; 2103c602fabSXin LI } 2113c602fabSXin LI 212ee67461eSJoseph Mingrone switch (GET_U_1(hdr->nflog_family)) { 2133c602fabSXin LI 214*0a7e5f1fSJoseph Mingrone case NFLOG_AF_INET: 2153c602fabSXin LI ip_print(ndo, p, length); 2163c602fabSXin LI break; 2173c602fabSXin LI 218*0a7e5f1fSJoseph Mingrone case NFLOG_AF_INET6: 2193c602fabSXin LI ip6_print(ndo, p, length); 2203c602fabSXin LI break; 2213c602fabSXin LI 2223c602fabSXin LI default: 2233c602fabSXin LI if (!ndo->ndo_eflag) 2243c602fabSXin LI nflog_hdr_print(ndo, hdr, 225ee67461eSJoseph Mingrone length + NFLOG_HDR_LEN); 2263c602fabSXin LI 2273c602fabSXin LI if (!ndo->ndo_suppress_default_print) 2283c602fabSXin LI ND_DEFAULTPRINT(p, caplen); 2293c602fabSXin LI break; 2303c602fabSXin LI } 2313c602fabSXin LI 232ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += h_size - NFLOG_HDR_LEN; 233ee67461eSJoseph Mingrone return; 234ee67461eSJoseph Mingrone trunc: 235ee67461eSJoseph Mingrone nd_print_trunc(ndo); 236ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += h_size - NFLOG_HDR_LEN; 2373c602fabSXin LI } 2383c602fabSXin LI 239ee67461eSJoseph Mingrone #endif /* DLT_NFLOG */ 240