summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2008-08-12 04:44:35 +0000
committerAnders Broman <anders.broman@ericsson.com>2008-08-12 04:44:35 +0000
commit3eadb385c3280a23cd277d8dbc57a33e4f6aecc3 (patch)
tree6d6b85f9c2dd3a8f248f104e4d79dd0b8c8f6769
parent5906f69b880d1959763d10490da91bc2ae2b3fb7 (diff)
downloadwireshark-3eadb385c3280a23cd277d8dbc57a33e4f6aecc3.tar.gz
From Alexey Neyman:
Implement dissector for IPMB (DLT_IPMB_LINUX, 209). svn path=/trunk/; revision=25986
-rw-r--r--capture_info.c6
-rw-r--r--epan/address.h3
-rw-r--r--epan/dissectors/Makefile.common2
-rw-r--r--epan/dissectors/packet-i2c.c306
-rw-r--r--epan/dissectors/packet-i2c.h29
-rw-r--r--epan/libwireshark.def1
-rw-r--r--epan/packet.h2
-rw-r--r--gtk/capture_info_dlg.c4
-rw-r--r--wiretap/libpcap.c134
-rw-r--r--wiretap/wtap.c5
-rw-r--r--wiretap/wtap.h9
11 files changed, 481 insertions, 20 deletions
diff --git a/capture_info.c b/capture_info.c
index 9b7a51ea05..1e0c7cae4a 100644
--- a/capture_info.c
+++ b/capture_info.c
@@ -57,6 +57,7 @@
#include <epan/dissectors/packet-ipfc.h>
#include <epan/dissectors/packet-arcnet.h>
#include <epan/dissectors/packet-enc.h>
+#include <epan/dissectors/packet-i2c.h>
static void capture_info_packet(
packet_counts *counts, gint wtap_linktype, const guchar *pd, guint32 caplen, union wtap_pseudo_header *pseudo_header);
@@ -88,6 +89,8 @@ void capture_info_open(capture_options *capture_opts)
info_data.counts.vines = 0;
info_data.counts.other = 0;
info_data.counts.arp = 0;
+ info_data.counts.i2c_event = 0;
+ info_data.counts.i2c_data = 0;
info_data.wtap = NULL;
info_data.ui.counts = &info_data.counts;
@@ -334,6 +337,9 @@ capture_info_packet(packet_counts *counts, gint wtap_linktype, const guchar *pd,
case WTAP_ENCAP_PPI:
capture_ppi(pd, caplen, counts);
break;
+ case WTAP_ENCAP_I2C:
+ capture_i2c(pseudo_header, counts);
+ break;
/* XXX - some ATM drivers on FreeBSD might prepend a 4-byte ATM
pseudo-header to DLT_ATM_RFC1483, with LLC header following;
we might have to implement that at some point. */
diff --git a/epan/address.h b/epan/address.h
index d5bf5ed7d1..c472502440 100644
--- a/epan/address.h
+++ b/epan/address.h
@@ -149,7 +149,8 @@ typedef enum {
PT_SBCCS, /* FICON */
PT_IDP, /* XNS IDP sockets */
PT_TIPC, /* TIPC PORT */
- PT_USB /* USB endpoint 0xffff means the host */
+ PT_USB, /* USB endpoint 0xffff means the host */
+ PT_I2C
} port_type;
/* Types of circuit IDs Wireshark knows about. */
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 254ce7e3b7..95a383408d 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -456,6 +456,7 @@ CLEAN_DISSECTOR_SRC = \
packet-hsrp.c \
packet-http.c \
packet-hyperscsi.c \
+ packet-i2c.c \
packet-iapp.c \
packet-iax2.c \
packet-icap.c \
@@ -952,6 +953,7 @@ DISSECTOR_INCLUDES = \
packet-hclnfsd.h \
packet-hpext.h \
packet-http.h \
+ packet-i2c.h \
packet-iax2.h \
packet-idp.h \
packet-ieee80211.h \
diff --git a/epan/dissectors/packet-i2c.c b/epan/dissectors/packet-i2c.c
new file mode 100644
index 0000000000..02dcfa4508
--- /dev/null
+++ b/epan/dissectors/packet-i2c.c
@@ -0,0 +1,306 @@
+/* packet-i2c.c
+ * Routines for I2C captures (using libpcap extensions)
+ *
+ * Pigeon Point Systems <www.pigeonpoint.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/prefs.h>
+
+#include "packet-i2c.h"
+
+static int proto_i2c = -1;
+
+static int hf_i2c_bus = -1;
+static int hf_i2c_event = -1;
+static int hf_i2c_flags = -1;
+static int hf_i2c_addr = -1;
+
+static gint ett_i2c = -1;
+
+enum {
+ SUB_DATA = 0,
+ SUB_IPMB,
+
+ SUB_MAX
+};
+
+typedef gboolean (*sub_checkfunc_t)(packet_info *);
+
+static dissector_handle_t sub_handles[SUB_MAX];
+static gint sub_selected = SUB_IPMB;
+
+/* I2C packet flags. */
+#define I2C_FLAG_RD 0x00000001
+#define I2C_FLAG_TEN 0x00000010
+#define I2C_FLAG_REV_DIR_ADDR 0x00002000
+#define I2C_FLAG_NOSTART 0x00004000
+
+/* I2C events. */
+#define I2C_EVENT_PROM_ON (1 << 0) /* Promiscuous mode: on */
+#define I2C_EVENT_PROM_OFF (1 << 1) /* Promiscuous mode: off */
+#define I2C_EVENT_ONLINE_ON (1 << 2) /* Online state: on */
+#define I2C_EVENT_ONLINE_OFF (1 << 3) /* Online state: off */
+#define I2C_EVENT_ATTACHED_ON (1 << 4) /* Attached state: on */
+#define I2C_EVENT_ATTACHED_OFF (1 << 5) /* Attached state: off */
+#define I2C_EVENT_PROM_OVFL_ON (1 << 6) /* Prom. queue overflow: on */
+#define I2C_EVENT_PROM_OVFL_OFF (1 << 7) /* Prom. queue overflow: off */
+#define I2C_EVENT_OVFL_ON (1 << 8) /* Queue overflow: on */
+#define I2C_EVENT_OVFL_OFF (1 << 9) /* Queue overflow: off */
+
+/* I2C errors. */
+#define I2C_EVENT_ERR_DATA_LO (1 << 16) /* Unable to drive data LO */
+#define I2C_EVENT_ERR_DATA_HI (1 << 17) /* Unable to drive data HI */
+#define I2C_EVENT_ERR_CLOCK_LO (1 << 18) /* Unable to drive clock LO */
+#define I2C_EVENT_ERR_CLOCK_HI (1 << 19) /* Unable to drive clock HI */
+#define I2C_EVENT_ERR_CLOCK_TO (1 << 20) /* Clock low timeout */
+#define I2C_EVENT_ERR_PHYS (1 << 21) /* The I2C bus controller
+ has been physically
+ disconnected from the bus */
+#define I2C_EVENT_ERR_FAIL (1 << 22) /* Undiagnosed failure */
+
+void
+capture_i2c(union wtap_pseudo_header *pseudo_header, packet_counts *ld)
+{
+ if (pseudo_header->i2c.is_event) {
+ ld->i2c_event++;
+ } else {
+ ld->i2c_data++;
+ }
+}
+
+static const char *
+i2c_get_event_desc(int event)
+{
+ const char *desc;
+
+ switch (event & 0x0000ffff) {
+ case I2C_EVENT_PROM_ON:
+ desc = "Promiscuous mode is enabled";
+ break;
+ case I2C_EVENT_PROM_OFF:
+ desc = "Promiscuous mode is disabled";
+ break;
+ case I2C_EVENT_ONLINE_ON:
+ desc = "The I2C controller is operational";
+ break;
+ case I2C_EVENT_ONLINE_OFF:
+ desc = "The I2C controller is non-operational";
+ break;
+ case I2C_EVENT_ATTACHED_ON:
+ desc = "The I2C controller is attached to an I2C bus";
+ break;
+ case I2C_EVENT_ATTACHED_OFF:
+ desc = "The I2C controller is detached from an I2C bus";
+ if (event & I2C_EVENT_ERR_DATA_LO) {
+ desc = "The I2C controller is detached from an I2C bus: "
+ "unable to drive data LO";
+ } else if (event & I2C_EVENT_ERR_DATA_HI) {
+ desc = "The I2C controller is detached from an I2C bus: "
+ "unable to drive data HI";
+ } else if (event & I2C_EVENT_ERR_CLOCK_LO) {
+ desc = "The I2C controller is detached from an I2C bus: "
+ "unable to drive clock LO";
+ } else if (event & I2C_EVENT_ERR_CLOCK_HI) {
+ desc = "The I2C controller is detached from an I2C bus: "
+ "unable to drive clock HI";
+ } else if (event & I2C_EVENT_ERR_CLOCK_TO) {
+ desc = "The I2C controller is detached from an I2C bus: "
+ "clock low timeout";
+ } else if (event & I2C_EVENT_ERR_PHYS) {
+ desc = "The I2C controller is detached from an I2C bus: "
+ "the I2C bus controller has been physically "
+ "disconnected from the bus";
+ } else if (event & I2C_EVENT_ERR_FAIL) {
+ desc = "The I2C controller is detached from an I2C bus: "
+ "undiagnosed failure";
+ }
+ break;
+ case I2C_EVENT_PROM_OVFL_ON:
+ desc = "The incoming promiscuous data buffer has been overrun; "
+ "some data is lost";
+ break;
+ case I2C_EVENT_PROM_OVFL_OFF:
+ desc = "The incoming promiscuous data buffer is available";
+ break;
+ case I2C_EVENT_OVFL_ON:
+ desc = "The incoming I2C data buffer has been overrun; "
+ "some data is lost";
+ break;
+ case I2C_EVENT_OVFL_OFF:
+ desc = "The incoming I2C data buffer is available";
+ break;
+ default:
+ desc = "<unknown state event>";
+ break;
+ }
+
+ return desc;
+}
+
+static gboolean
+sub_check_ipmb(packet_info *pinfo)
+{
+ if (pinfo->pseudo_header->i2c.flags & I2C_FLAG_RD) {
+ /* Master-receive transactions are not possible on IPMB */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static sub_checkfunc_t sub_check[SUB_MAX] = {
+ NULL, /* raw data */
+ sub_check_ipmb /* IPMI */
+};
+
+static void
+dissect_i2c(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *i2c_tree = NULL;
+ int is_event, bus, flags, addr, len;
+
+ is_event = pinfo->pseudo_header->i2c.is_event;
+ flags = pinfo->pseudo_header->i2c.flags;
+ bus = pinfo->pseudo_header->i2c.bus;
+ len = tvb_length(tvb);
+ if (is_event) {
+ addr = 0;
+ } else {
+ if (len == 0) {
+ THROW(ReportedBoundsError);
+ }
+ /* Report 7-bit hardware address */
+ addr = tvb_get_guint8(tvb, 0) >> 1;
+ }
+
+ pinfo->ptype = PT_I2C;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ if (is_event)
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "I2C Event");
+ else
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "I2C %s",
+ (flags & I2C_FLAG_RD) ? "Read" : "Write");
+ }
+
+ if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
+ col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "I2C-%d", bus);
+ }
+
+ if (check_col(pinfo->cinfo, COL_DEF_DST)) {
+ if (is_event)
+ col_add_fstr(pinfo->cinfo, COL_DEF_DST, "----");
+ else
+ col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%02x", addr);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (is_event)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ i2c_get_event_desc(flags));
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "I2C %s, %d bytes",
+ (flags & I2C_FLAG_RD) ? "Read" : "Write", len);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_i2c, tvb, 0, -1,
+ "Inter-Integrated Circuit (%s)",
+ is_event ? "Event" : "Data");
+
+ i2c_tree = proto_item_add_subtree(ti, ett_i2c);
+ proto_tree_add_uint_format(i2c_tree, hf_i2c_bus, tvb, 0, 0, bus,
+ "Bus: I2C-%d", bus);
+
+ if (is_event) {
+ proto_tree_add_uint_format(i2c_tree, hf_i2c_event, tvb, 0, 0,
+ flags, "Event: %s (0x%08x)",
+ i2c_get_event_desc(flags), flags);
+ } else {
+ proto_tree_add_uint_format_value(i2c_tree, hf_i2c_addr, tvb, 0, 1,
+ addr, "0x%02x%s", addr, addr ? "" : " (General Call)");
+ proto_tree_add_uint_format(i2c_tree, hf_i2c_flags, tvb, 0, 0,
+ flags, "Flags: 0x%08x", flags);
+ }
+ }
+
+ if (!is_event) {
+ if (!sub_check[sub_selected] || sub_check[sub_selected](pinfo)) {
+ call_dissector(sub_handles[sub_selected], tvb, pinfo, tree);
+ } else {
+ call_dissector(sub_handles[SUB_DATA], tvb, pinfo, tree);
+ }
+ }
+}
+
+void
+proto_register_i2c(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_i2c_bus, { "Bus ID", "i2c.bus", FT_UINT8, BASE_DEC, NULL, 0, "", HFILL }},
+ { &hf_i2c_addr, { "Target address", "i2c.addr", FT_UINT8, BASE_HEX, NULL, 0, "", HFILL }},
+ { &hf_i2c_event, { "Event", "i2c.event", FT_UINT32, BASE_HEX, NULL, 0, "", HFILL }},
+ { &hf_i2c_flags, { "Flags", "i2c.flags", FT_UINT32, BASE_HEX, NULL, 0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_i2c
+ };
+ static const enum_val_t sub_enum_vals[] = {
+ { "none", "None (raw I2C)", SUB_DATA },
+ { "ipmb", "IPMB", SUB_IPMB },
+ { NULL, NULL, 0 }
+ };
+ module_t *m;
+
+ proto_i2c = proto_register_protocol("Inter-Integrated Circuit", "I2C", "i2c");
+ proto_register_field_array(proto_i2c, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ m = prefs_register_protocol(proto_i2c, NULL);
+ prefs_register_enum_preference(m, "type", "Bus type", "How the I2C messages are interpreted",
+ &sub_selected, sub_enum_vals, FALSE);
+}
+
+void
+proto_reg_handoff_i2c(void)
+{
+ static gboolean inited = FALSE;
+ if (!inited) {
+ dissector_handle_t i2c_handle;
+
+ sub_handles[SUB_DATA] = find_dissector("data");
+ sub_handles[SUB_IPMB] = find_dissector("ipmi");
+ i2c_handle = create_dissector_handle(dissect_i2c, proto_i2c);
+ dissector_add("wtap_encap", WTAP_ENCAP_I2C, i2c_handle);
+ inited = TRUE;
+ }
+}
diff --git a/epan/dissectors/packet-i2c.h b/epan/dissectors/packet-i2c.h
new file mode 100644
index 0000000000..0510e1bb9f
--- /dev/null
+++ b/epan/dissectors/packet-i2c.h
@@ -0,0 +1,29 @@
+/* packet-i2c.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_I2C_H__
+#define __PACKET_I2C_H__
+
+void capture_i2c(union wtap_pseudo_header *, packet_counts *);
+
+#endif
diff --git a/epan/libwireshark.def b/epan/libwireshark.def
index 393bddab31..933f1928cb 100644
--- a/epan/libwireshark.def
+++ b/epan/libwireshark.def
@@ -50,6 +50,7 @@ capture_enc
capture_eth
capture_fddi
capture_fr
+capture_i2c
capture_ieee80211
capture_ipfc
capture_llap
diff --git a/epan/packet.h b/epan/packet.h
index 7d2f5f2baf..6d4896fe6b 100644
--- a/epan/packet.h
+++ b/epan/packet.h
@@ -70,6 +70,8 @@ typedef struct _packet_counts {
gint other;
gint total;
gint arp;
+ gint i2c_event;
+ gint i2c_data;
} packet_counts;
/** Number of packet counts. */
diff --git a/gtk/capture_info_dlg.c b/gtk/capture_info_dlg.c
index 8f223a2b7e..c7fec02910 100644
--- a/gtk/capture_info_dlg.c
+++ b/gtk/capture_info_dlg.c
@@ -168,6 +168,10 @@ capture_options *capture_opts)
info->counts[10].value_ptr = &(cinfo->counts->vines);
info->counts[11].title = "Other";
info->counts[11].value_ptr = &(cinfo->counts->other);
+ info->counts[12].title = "I2C Events";
+ info->counts[12].value_ptr = &(cinfo->counts->i2c_event);
+ info->counts[13].title = "I2C Data";
+ info->counts[13].value_ptr = &(cinfo->counts->i2c_data);
/*
* Create the dialog window, with a title that includes the interface.
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c
index 386d638dbe..7f1609f4fc 100644
--- a/wiretap/libpcap.c
+++ b/wiretap/libpcap.c
@@ -99,6 +99,14 @@
#define LAPD_SLL_PROTOCOL_OFFSET 14 /* protocol, should be ETH_P_LAPD - 2 bytes */
#define LAPD_SLL_LEN 16 /* length of the header */
+/*
+ * I2C link-layer on-disk format
+ */
+struct i2c_file_hdr {
+ guint8 bus;
+ guint8 flags[4];
+};
+
/* See source to the "libpcap" library for information on the "libpcap"
file format. */
@@ -157,6 +165,10 @@ static gboolean libpcap_get_erf_subheader(const guint8 *erf_subhdr,
union wtap_pseudo_header *pseudo_header, guint * size);
static gboolean libpcap_read_erf_subheader(FILE_T fh,
union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_, guint * size);
+static gboolean libpcap_get_i2c_pseudoheader(const struct i2c_file_hdr *i2c_hdr,
+ union wtap_pseudo_header *pseudo_header);
+static gboolean libpcap_read_i2c_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length,
int *err);
static void libpcap_close(wtap *wth);
@@ -349,9 +361,9 @@ static const struct {
{ 127, WTAP_ENCAP_IEEE_802_11_WLAN_RADIOTAP }, /* 802.11 plus radiotap WLAN header */
{ 128, WTAP_ENCAP_TZSP }, /* Tazmen Sniffer Protocol */
{ 129, WTAP_ENCAP_ARCNET_LINUX },
- { 130, WTAP_ENCAP_JUNIPER_MLPPP }, /* Juniper MLPPP on ML-, LS-, AS- PICs */
- { 131, WTAP_ENCAP_JUNIPER_MLFR }, /* Juniper MLFR (FRF.15) on ML-, LS-, AS- PICs */
- { 133, WTAP_ENCAP_JUNIPER_GGSN},
+ { 130, WTAP_ENCAP_JUNIPER_MLPPP }, /* Juniper MLPPP on ML-, LS-, AS- PICs */
+ { 131, WTAP_ENCAP_JUNIPER_MLFR }, /* Juniper MLFR (FRF.15) on ML-, LS-, AS- PICs */
+ { 133, WTAP_ENCAP_JUNIPER_GGSN},
/*
* Values 132-134, 136 not listed here are reserved for use
* in Juniper hardware.
@@ -403,8 +415,8 @@ static const struct {
* but it is used for some Linux IP filtering (ipfilter?).
*/
- /* Ethernet PPPoE frames captured on a service PIC */
- { 167, WTAP_ENCAP_JUNIPER_PPPOE },
+ /* Ethernet PPPoE frames captured on a service PIC */
+ { 167, WTAP_ENCAP_JUNIPER_PPPOE },
/*
* 168 is reserved for more Juniper private-chassis-
@@ -424,16 +436,16 @@ static const struct {
{ 177, WTAP_ENCAP_LINUX_LAPD },
- /* Ethernet frames prepended with meta-information */
- { 178, WTAP_ENCAP_JUNIPER_ETHER },
- /* PPP frames prepended with meta-information */
- { 179, WTAP_ENCAP_JUNIPER_PPP },
- /* Frame-Relay frames prepended with meta-information */
- { 180, WTAP_ENCAP_JUNIPER_FRELAY },
- /* C-HDLC frames prepended with meta-information */
- { 181, WTAP_ENCAP_JUNIPER_CHDLC },
- /* VOIP Frames prepended with meta-information */
- { 183, WTAP_ENCAP_JUNIPER_VP },
+ /* Ethernet frames prepended with meta-information */
+ { 178, WTAP_ENCAP_JUNIPER_ETHER },
+ /* PPP frames prepended with meta-information */
+ { 179, WTAP_ENCAP_JUNIPER_PPP },
+ /* Frame-Relay frames prepended with meta-information */
+ { 180, WTAP_ENCAP_JUNIPER_FRELAY },
+ /* C-HDLC frames prepended with meta-information */
+ { 181, WTAP_ENCAP_JUNIPER_CHDLC },
+ /* VOIP Frames prepended with meta-information */
+ { 183, WTAP_ENCAP_JUNIPER_VP },
/* raw USB packets */
{ 186, WTAP_ENCAP_USB },
/* Bluetooth HCI UART transport (part H:4) frames, like hcidump */
@@ -445,16 +457,18 @@ static const struct {
/* CAN 2.0b frame */
{ 190, WTAP_ENCAP_CAN20B },
/* Per-Packet Information header */
- { 192, WTAP_ENCAP_PPI },
+ { 192, WTAP_ENCAP_PPI },
/* IEEE 802.15.4 Wireless PAN */
{ 195, WTAP_ENCAP_IEEE802_15_4 },
/* SITA File Encapsulation */
- { 196, WTAP_ENCAP_SITA },
+ { 196, WTAP_ENCAP_SITA },
/* Endace Record File Encapsulation */
- { 197, WTAP_ENCAP_ERF },
+ { 197, WTAP_ENCAP_ERF },
{ 199, WTAP_ENCAP_IPMB },
/* Bluetooth HCI UART transport (part H:4) frames, like hcidump */
{ 201, WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR },
+ /* IPMB/I2C */
+ { 209, WTAP_ENCAP_I2C },
/* FlexRay frame */
{ 210, WTAP_ENCAP_FLEXRAY },
/* MOST frame */
@@ -1506,6 +1520,29 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
wth->data_offset += size;
break;
+ case WTAP_ENCAP_I2C:
+ if (packet_size < sizeof (struct i2c_file_hdr)) {
+ /*
+ * Uh-oh, the packet isn't big enough to even
+ * have a pseudo-header.
+ */
+ *err = WTAP_ERR_BAD_RECORD;
+ *err_info = g_strdup_printf("libpcap: I2C file has a %u-byte packet, too small to have even a I2C pseudo-header\n",
+ packet_size);
+ return FALSE;
+ }
+ if (!libpcap_read_i2c_pseudoheader(wth->fh, &wth->pseudo_header,
+ err, err_info))
+ return FALSE; /* Read error */
+
+ /*
+ * Don't count the pseudo-header as part of the packet.
+ */
+ orig_size -= sizeof (struct i2c_file_hdr);
+ packet_size -= sizeof (struct i2c_file_hdr);
+ wth->data_offset += sizeof (struct i2c_file_hdr);
+ break;
+
}
buffer_assure_space(wth->frame_buffer, packet_size);
@@ -1664,6 +1701,14 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
return FALSE;
}
break;
+
+ case WTAP_ENCAP_I2C:
+ if (!libpcap_read_i2c_pseudoheader(wth->random_fh, pseudo_header,
+ err, err_info)) {
+ /* Read error */
+ return FALSE;
+ }
+ break;
}
/*
@@ -2262,6 +2307,35 @@ libpcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
}
static gboolean
+libpcap_get_i2c_pseudoheader(const struct i2c_file_hdr *i2c_hdr, union wtap_pseudo_header *pseudo_header)
+{
+ pseudo_header->i2c.is_event = i2c_hdr->bus & 0x80 ? 1 : 0;
+ pseudo_header->i2c.bus = i2c_hdr->bus & 0x7f;
+ pseudo_header->i2c.flags = pntohl(&i2c_hdr->flags);
+
+ return TRUE;
+}
+
+static gboolean
+libpcap_read_i2c_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+{
+ struct i2c_file_hdr i2c_hdr;
+ int bytes_read;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(&i2c_hdr, 1, sizeof (i2c_hdr), fh);
+ if (bytes_read != sizeof (i2c_hdr)) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ return libpcap_get_i2c_pseudoheader(&i2c_hdr, pseudo_header);
+
+}
+
+static gboolean
libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
{
int bytes_read;
@@ -2459,6 +2533,7 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
guint8 mtp2_hdr[MTP2_HDR_LEN];
guint8 sita_hdr[SITA_HDR_LEN];
guint8 erf_hdr[ sizeof(struct erf_mc_phdr)];
+ struct i2c_file_hdr i2c_hdr;
int hdrsize, size;
switch (wdh->encap) {
@@ -2509,6 +2584,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
}
break;
+ case WTAP_ENCAP_I2C:
+ hdrsize = sizeof (struct i2c_file_hdr);
+ break;
+
default:
hdrsize = 0;
break;
@@ -2783,6 +2862,25 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
}
wdh->bytes_dumped += size;
break;
+
+ case WTAP_ENCAP_I2C:
+ /*
+ * Write the I2C header.
+ */
+ memset(&i2c_hdr, 0, sizeof(i2c_hdr));
+ i2c_hdr.bus = pseudo_header->i2c.bus |
+ (pseudo_header->i2c.is_event ? 0x80 : 0x00);
+ phtonl((guint8 *)&i2c_hdr.flags, pseudo_header->i2c.flags);
+ nwritten = fwrite(&i2c_hdr, 1, sizeof(i2c_hdr), wdh->fh);
+ if (nwritten != sizeof(i2c_hdr)) {
+ if (nwritten == 0 && ferror(wdh->fh))
+ *err = errno;
+ else
+ *err = WTAP_ERR_SHORT_WRITE;
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(i2c_hdr);
+ break;
}
nwritten = wtap_dump_file_write(wdh, pd, phdr->caplen);
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index 64c2f0a66b..4075e58cbd 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -424,7 +424,10 @@ static struct encap_type_info encap_table_base[] = {
{ "EyeSDN Layer 1 event", "layer1-event" },
/* WTAP_ENCAP_X2E_SERIAL */
- { "X2E serial line capture", "x2e-serial" }
+ { "X2E serial line capture", "x2e-serial" },
+
+ /* WTAP_ENCAP_I2C */
+ { "I2C", "i2c" }
};
gint wtap_num_encap_types = sizeof(encap_table_base) / sizeof(struct encap_type_info);
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 58047fc8c0..20416e719f 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -206,6 +206,7 @@ extern "C" {
#define WTAP_ENCAP_CAN20B 109
#define WTAP_ENCAP_LAYER1_EVENT 110
#define WTAP_ENCAP_X2E_SERIAL 111
+#define WTAP_ENCAP_I2C 112
#define WTAP_NUM_ENCAP_TYPES wtap_get_num_encap_types()
@@ -736,6 +737,13 @@ struct bthci_phdr {
struct l1event_phdr {
gboolean uton;
};
+
+/* * I2C pseudo header */
+struct i2c_phdr {
+ guint8 is_event;
+ guint8 bus;
+ guint32 flags;
+};
union wtap_pseudo_header {
struct eth_phdr eth;
@@ -757,6 +765,7 @@ union wtap_pseudo_header {
struct sita_phdr sita;
struct bthci_phdr bthci;
struct l1event_phdr l1event;
+ struct i2c_phdr i2c;
};
struct wtap_nstime {