aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/pcap-common.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2014-02-08 19:09:41 -0800
committerAnders Broman <a.broman58@gmail.com>2014-03-06 05:53:08 +0000
commite2ed48a8d38e7a885d47ba213e7deb72e18ca3d9 (patch)
treeec2c33d65a7a150aae3f9de9616643469369b26f /wiretap/pcap-common.c
parentdc7d5f97eb3741af9bd16c0e8335b80f6829d9a6 (diff)
Have NFLOG TLV type and length be in host byte order.
When capturing, they'll be in host byte order. The top of the libpcap trunk and 1.5 branch, when reading a file, will, if necessary, byte-swap the type and length values so that they're in the byte order of the host reading the file (rather than the host that wrote the file). Do the same when we read a file, and have the NFLOG dissector assume host byte order for those fields. Change-Id: I493aed1e07b626af1157d75f3bc293b0a694ad07 Reviewed-on: https://code.wireshark.org/review/148 Reviewed-by: Evan Huus <eapache@gmail.com> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'wiretap/pcap-common.c')
-rw-r--r--wiretap/pcap-common.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c
index 34f9db2792..393deb38f8 100644
--- a/wiretap/pcap-common.c
+++ b/wiretap/pcap-common.c
@@ -1293,6 +1293,81 @@ pcap_byteswap_linux_usb_pseudoheader(struct wtap_pkthdr *phdr, guint8 *pd,
}
}
+struct nflog_hdr {
+ guint8 nflog_family; /* address family */
+ guint8 nflog_version; /* version */
+ guint16 nflog_rid; /* resource ID */
+};
+
+struct nflog_tlv {
+ guint16 tlv_length; /* tlv length */
+ guint16 tlv_type; /* tlv type */
+ /* value follows this */
+};
+
+static void
+pcap_byteswap_nflog_pseudoheader(struct wtap_pkthdr *phdr, guint8 *pd)
+{
+ guint packet_size;
+ guint8 *p;
+ struct nflog_hdr *nfhdr;
+ struct nflog_tlv *tlv;
+ guint size;
+
+ /*
+ * Minimum of captured and actual length (just in case the
+ * actual length < the captured length, which Should Never
+ * Happen).
+ */
+ packet_size = phdr->caplen;
+ if (packet_size > phdr->len)
+ packet_size = phdr->len;
+
+ if (packet_size < sizeof(struct nflog_hdr)) {
+ /* Not enough data to have any TLVs. */
+ return;
+ }
+
+ p = pd;
+ nfhdr = (struct nflog_hdr *)pd;
+ if (!(nfhdr->nflog_version) == 0) {
+ /* Unknown NFLOG version */
+ return;
+ }
+
+ packet_size -= (guint)sizeof(struct nflog_hdr);
+ p += sizeof(struct nflog_hdr);
+
+ while (packet_size >= sizeof(struct nflog_tlv)) {
+ tlv = (struct nflog_tlv *) p;
+
+ /* Swap the type and length. */
+ PBSWAP16((guint8 *)&tlv->tlv_type);
+ PBSWAP16((guint8 *)&tlv->tlv_length);
+
+ /* Get the length of the TLV. */
+ size = tlv->tlv_length;
+ if (size % 4 != 0)
+ size += 4 - size % 4;
+
+ /* Is the TLV's length less than the minimum? */
+ if (size < sizeof(struct nflog_tlv)) {
+ /* Yes. Give up now. */
+ return;
+ }
+
+ /* Do we have enough data for the full TLV? */
+ if (packet_size < size) {
+ /* No. */
+ return;
+ }
+
+ /* Skip over the TLV. */
+ packet_size -= size;
+ p += size;
+ }
+}
+
static gboolean
pcap_read_bt_pseudoheader(FILE_T fh,
union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
@@ -1877,6 +1952,11 @@ pcap_read_post_process(int file_type, int wtap_encap,
phdr->pseudo_header.eth.fcs_len = 4;
break;
+ case WTAP_ENCAP_NFLOG:
+ if (bytes_swapped)
+ pcap_byteswap_nflog_pseudoheader(phdr, pd);
+ break;
+
default:
break;
}