最近要调试chromium工程,感到自己的开发机台渣了。借着这个理由,换个新的开发机,安慰自己一下。要是没找到理由,自己会惭愧的,还真说服不了自己换新计算机。
将内存升到64GB, 用起来好爽。主板上还有4个内存插槽,还能加4个单条的16GB内存。等下一步,再找个理由(估计很难),升到128GB. 华硕主板做的是真强。
上午在捣鼓新开发机,将旧开发机的ssd和机械硬盘加到新开发机上了。装开发环境。
想起上周,想做的wireshark的arp分析插件。就拿这个工程来试试刀,看看编译和调试的感觉是不是好很多。
有以前做好的虚拟机,wireshark开发环境都是好的。这回,给虚拟机分配32GB内存,CPU只能分2x2.
开始做wireshark-arp分析插件。
ARP协议简单. 做的时候,要接管wireshark的内建的ARP分析(不要改wireshark源码,只由插件代码来接管), 这个实验了好久. 去围观和调试了wireshark的arp协议分析的实现, 抄代码挺爽的, 能边做边学。
从上一个插件代码实验的博文,将主实现拷贝下来做实验,发现每行结尾的回车换行都变了. 应该是csdn博客的bug, 以前有拷贝代码的按钮,拷贝下来和原始代码一样,现在没这个按钮了, 拷贝下来都变形了. 特别是Makefile.
packet-foo-arp.c
在网上找了一份将ARP协议的ppt
protocol_arp_rarp.pdf
通过对ARP问答包的分别分析,可以看出,ARP发送者是多播,ARP回答者是单播.
ARP protocol parse by foo plugin
TAG_ARP_HEADER.hardware_type = Ethernet (0x0001)
TAG_ARP_HEADER.protocol_type = IPv4 (0x0800)
TAG_ARP_HEADER.hardware_size = 6
TAG_ARP_HEADER.protocol_size = 4
TAG_ARP_HEADER.opt_code = request (0x0001)
sender mac = 8C:F2:28:4B:E3:2C
sender ip = 192.168.2.2
request mac = 00:00:00:00:00:00
request ip = 192.168.2.66
nice, parse ok
ARP protocol parse by foo plugin
TAG_ARP_HEADER.hardware_type = Ethernet (0x0001)
TAG_ARP_HEADER.protocol_type = IPv4 (0x0800)
TAG_ARP_HEADER.hardware_size = 6
TAG_ARP_HEADER.protocol_size = 4
TAG_ARP_HEADER.opt_code = reply (0x0002)
sender mac = 4C:ED:FB:CB:44:1C
sender ip = 192.168.2.66
request mac = 8C:F2:28:4B:E3:2C
request ip = 192.168.2.2
nice, parse ok
通过分析,可以看出这对ARP应答, 是我的路由器(网关)在问我的新开发机的mac和IP对应关系. 他为啥要问呢? 已经连接了好久。
wireshark插件要配好一套开发环境,单是主实现,编译不出能用的插件。
配插件环境,太折腾了,不想每个实验都搞一个新插件工程。如果不是正式工程,不想整新插件工程了。
将环境搭好了,配好一个foo插件工程, 在这个工程中作各种协议分析的实验。
// @file packet-foo.c
// @brief the foo plugin parse ARP protocol
// @ref http://www.dgtech.com/foo/sys/www/docs/html/
// https://www.wireshark.org/docs/wsdg_html_chunked/
// https://www.wireshark.org/docs/wsdg_html_chunked/PartDevelopment.html
// https://www.wireshark.org/docs/wsdg_html_chunked/ChDissectAdd.html#idm1589259872
// @note how to use foo plugin
// open a pcap file or capture any packet, select a tcp frame(have payload), Decode as ... => foo => ok
#include
#include
#include
#include
#include "config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "packet-foo.h"
#define PROTOCOL_FULL_NAME_FOO "ARP protocol parse by foo plugin"
#define PROTOCOL_SHORT_NAME_FOO "foo"
#define PROTOCOL_DISPLAY_FILTER_NAME_FOO PROTOCOL_SHORT_NAME_FOO
// interface declare for plugin.c (plugin dll interface plugin_register(), plugin_reg_handoff())
void proto_register_foo(void);
void proto_reg_handoff_foo(void);
static dissector_handle_t dissector_handle_foo = NULL;
static int protocol_handle_foo = -1;
static int proto_arp = 1;
// hf means "header field name"
static int hf_foo_message = -1;
static int hf_foo_pdu_type = -1;
// 要注册的字段信息数组, use use proto_register_field_array to register
static hf_register_info hf[] = {
{ &hf_foo_message,
{
"FOO message", // field name
"foo.msg", // field short name
FT_STRING, // field type, see ftypes.h
BASE_NONE, // data base type, see proto.h field_display_e
NULL, // value_string
0x0, // bitmask
NULL, // Brief description of field
HFILL // info fill by proto routines
}
},
{ &hf_foo_pdu_type,
{
"FOO PDU Type", // field name
"foo.type", // field short name
FT_UINT8, // field type, see ftypes.h
BASE_DEC, // data base type, see proto.h field_display_e
NULL, // value_string
0x0, // bitmask
NULL, // Brief description of field
HFILL // info fill by proto routines
}
}
};
static gint ett_foo = -1;
static gint ett_foo_subtree_1 = -1;
// ett means "protocol subtree array"
static gint *ett[] = {
&ett_foo,
&ett_foo_subtree_1
};
const value_string arp_hrd_vals[] = {
{ ARPHRD_NETROM, "NET/ROM pseudo" },
{ ARPHRD_ETHER, "Ethernet" },
{ ARPHRD_EETHER, "Experimental Ethernet" },
{ ARPHRD_AX25, "AX.25" },
{ ARPHRD_PRONET, "ProNET" },
{ ARPHRD_CHAOS, "Chaos" },
{ ARPHRD_IEEE802, "IEEE 802" },
{ ARPHRD_ARCNET, "ARCNET" },
{ ARPHRD_HYPERCH, "Hyperchannel" },
{ ARPHRD_LANSTAR, "Lanstar" },
{ ARPHRD_AUTONET, "Autonet Short Address" },
{ ARPHRD_LOCALTLK, "Localtalk" },
{ ARPHRD_LOCALNET, "LocalNet" },
{ ARPHRD_ULTRALNK, "Ultra link" },
{ ARPHRD_SMDS, "SMDS" },
{ ARPHRD_DLCI, "Frame Relay DLCI" },
{ ARPHRD_ATM, "ATM" },
{ ARPHRD_HDLC, "HDLC" },
{ ARPHRD_FIBREC, "Fibre Channel" },
{ ARPHRD_ATM2225, "ATM (RFC 2225)" },
{ ARPHRD_SERIAL, "Serial Line" },
{ ARPHRD_ATM2, "ATM" },
{ ARPHRD_MS188220, "MIL-STD-188-220" },
{ ARPHRD_METRICOM, "Metricom STRIP" },
{ ARPHRD_IEEE1394, "IEEE 1394.1995" },
{ ARPHRD_MAPOS, "MAPOS" },
{ ARPHRD_TWINAX, "Twinaxial" },
{ ARPHRD_EUI_64, "EUI-64" },
{ ARPHRD_HIPARP, "HIPARP" },
{ ARPHRD_IP_ARP_ISO_7816_3, "IP and ARP over ISO 7816-3" },
{ ARPHRD_ARPSEC, "ARPSec" },
{ ARPHRD_IPSEC_TUNNEL, "IPsec tunnel" },
{ ARPHRD_INFINIBAND, "InfiniBand" },
{ ARPHRD_TIA_102_PRJ_25_CAI, "TIA-102 Project 25 CAI" },
{ ARPHRD_WIEGAND_INTERFACE, "Wiegand Interface" },
{ ARPHRD_PURE_IP, "Pure IP" },
{ ARPHDR_HW_EXP1, "Experimental 1" },
{ ARPHDR_HFI, "HFI" },
{ ARPHDR_HW_EXP2, "Experimental 2" },
/* Virtual ARP types for non ARP hardware used in Linux cooked mode. */
{ ARPHRD_LOOPBACK, "Loopback" },
{ ARPHRD_IPGRE, "GRE over IP" },
{ ARPHRD_NETLINK, "Netlink" },
{ 0, NULL } };
// epan/etypes.h export etype_vals
// WS_DLL_PUBLIC const value_string etype_vals[]; but it have not array size
const value_string my_etype_vals[] = {
{ ETHERTYPE_IP, "IPv4" },
{ ETHERTYPE_IPv6, "IPv6" },
{ ETHERTYPE_VLAN, "802.1Q Virtual LAN" },
{ ETHERTYPE_ARP, "ARP" },
{ ETHERTYPE_WLCCP, "Cisco Wireless Lan Context Control Protocol" },
{ ETHERTYPE_MINT, "Motorola Media Independent Network Transport" },
{ ETHERTYPE_CENTRINO_PROMISC, "IEEE 802.11 (Centrino promiscuous)" },
{ ETHERTYPE_XNS_IDP, "XNS Internet Datagram Protocol" },
{ ETHERTYPE_X25L3, "X.25 Layer 3" },
{ ETHERTYPE_WOL, "Wake on LAN" },
{ ETHERTYPE_WMX_M2M, "WiMax Mac-to-Mac" },
{ ETHERTYPE_EPL_V1, "EPL_V1" },
{ ETHERTYPE_REVARP, "RARP" },
{ ETHERTYPE_DEC_LB, "DEC LanBridge" },
{ ETHERTYPE_ATALK, "Appletalk" },
{ ETHERTYPE_SNA, "SNA-over-Ethernet" },
{ ETHERTYPE_DLR, "EtherNet/IP Device Level Ring" },
{ ETHERTYPE_AARP, "AARP" },
{ ETHERTYPE_IPX, "Netware IPX/SPX" },
{ ETHERTYPE_VINES_IP, "Vines IP" },
{ ETHERTYPE_VINES_ECHO, "Vines Echo" },
{ ETHERTYPE_TRAIN, "Netmon Train" },
/* Ethernet Loopback */
{ ETHERTYPE_LOOP, "Loopback" },
{ ETHERTYPE_FOUNDRY, "Foundry proprietary" },
{ ETHERTYPE_WCP, "Wellfleet Compression Protocol" },
{ ETHERTYPE_STP, "Spanning Tree Protocol" },
/* for ISMP, see RFC 2641, RFC 2642, RFC 2643 */
{ ETHERTYPE_ISMP, "Cabletron Interswitch Message Protocol" },
{ ETHERTYPE_ISMP_TBFLOOD, "Cabletron SFVLAN 1.8 Tag-Based Flood" },
/* In www.iana.org/assignments/ethernet-numbers, 8203-8205 description is
* Quantum Software. Now the company is called QNX Software Systems. */
{ ETHERTYPE_QNX_QNET6, "QNX 6 QNET protocol" },
{ ETHERTYPE_PPPOED, "PPPoE Discovery" },
{ ETHERTYPE_PPPOES, "PPPoE Session" },
{ ETHERTYPE_LINK_CTL, "HomePNA, wlan link local tunnel" },
{ ETHERTYPE_INTEL_ANS, "Intel ANS probe" },
{ ETHERTYPE_MS_NLB_HEARTBEAT, "MS NLB heartbeat" },
{ ETHERTYPE_JUMBO_LLC, "Jumbo LLC" },
{ ETHERTYPE_HOMEPLUG, "Homeplug" },
{ ETHERTYPE_HOMEPLUG_AV, "Homeplug AV" },
{ ETHERTYPE_MRP, "MRP" },
{ ETHERTYPE_IEEE_802_1AD, "802.1ad Provider Bridge (Q-in-Q)" },
{ ETHERTYPE_MACSEC, "802.1AE (MACsec)" },
{ ETHERTYPE_IEEE_802_1AH, "802.1ah Provider Backbone Bridge (mac-in-mac)" },
{ ETHERTYPE_IEEE_802_1BR, "802.1br Bridge Port Extension E-Tag" },
{ ETHERTYPE_EAPOL, "802.1X Authentication" },
{ ETHERTYPE_RSN_PREAUTH, "802.11i Pre-Authentication" },
{ ETHERTYPE_MPLS, "MPLS label switched packet" },
{ ETHERTYPE_MPLS_MULTI, "MPLS multicast label switched packet" },
{ ETHERTYPE_3C_NBP_DGRAM, "3Com NBP Datagram" },
{ ETHERTYPE_DEC, "DEC proto" },
{ ETHERTYPE_DNA_DL, "DEC DNA Dump/Load" },
{ ETHERTYPE_DNA_RC, "DEC DNA Remote Console" },
{ ETHERTYPE_DNA_RT, "DEC DNA Routing" },
{ ETHERTYPE_LAT, "DEC LAT" },
{ ETHERTYPE_DEC_DIAG, "DEC Diagnostics" },
{ ETHERTYPE_DEC_CUST, "DEC Customer use" },
{ ETHERTYPE_DEC_SCA, "DEC LAVC/SCA" },
{ ETHERTYPE_DEC_LAST, "DEC LAST" },
{ ETHERTYPE_ETHBRIDGE, "Transparent Ethernet bridging" },
{ ETHERTYPE_CGMP, "Cisco Group Management Protocol" },
{ ETHERTYPE_GIGAMON, "Gigamon Header" },
{ ETHERTYPE_MSRP, "802.1Qat Multiple Stream Reservation Protocol" },
{ ETHERTYPE_MMRP, "802.1ak Multiple Mac Registration Protocol" },
{ ETHERTYPE_NSH, "Network Service Header" },
{ ETHERTYPE_AVBTP, "IEEE 1722 Audio Video Bridging Transport Protocol" },
{ ETHERTYPE_ROHC, "Robust Header Compression(RoHC)" },
{ ETHERTYPE_TRILL, "TRansparent Interconnection of Lots of Links" },
{ ETHERTYPE_L2ISIS, "Intermediate System to Intermediate System" },
{ ETHERTYPE_MAC_CONTROL, "MAC Control" },
{ ETHERTYPE_SLOW_PROTOCOLS, "Slow Protocols" },
{ ETHERTYPE_RTMAC, "Real-Time Media Access Control" },
{ ETHERTYPE_RTCFG, "Real-Time Configuration Protocol" },
{ ETHERTYPE_CDMA2000_A10_UBS, "CDMA2000 A10 Unstructured byte stream" },
{ ETHERTYPE_ATMOE, "ATM over Ethernet" },
{ ETHERTYPE_PROFINET, "PROFINET" },
{ ETHERTYPE_REALTEK, "Realtek Layer 2 Protocols" },
{ ETHERTYPE_AOE, "ATA over Ethernet" },
{ ETHERTYPE_ECATF, "EtherCAT frame" },
{ ETHERTYPE_TELKONET, "Telkonet powerline" },
{ ETHERTYPE_EPL_V2, "ETHERNET Powerlink v2" },
{ ETHERTYPE_XIMETA, "XiMeta Technology" },
{ ETHERTYPE_CSM_ENCAPS, "CSM_ENCAPS Protocol" },
{ ETHERTYPE_EXPERIMENTAL_ETH1, "Local Experimental Ethertype 1" },
{ ETHERTYPE_EXPERIMENTAL_ETH2, "Local Experimental Ethertype 2" },
{ ETHERTYPE_IEEE802_OUI_EXTENDED, "IEEE 802a OUI Extended Ethertype" },
{ ETHERTYPE_IEC61850_GOOSE, "IEC 61850/GOOSE" },
{ ETHERTYPE_IEC61850_GSE, "IEC 61850/GSE management services" },
{ ETHERTYPE_IEC61850_SV, "IEC 61850/SV (Sampled Value Transmission" },
{ ETHERTYPE_TIPC, "Transparent Inter Process Communication" },
{ ETHERTYPE_LLDP, "802.1 Link Layer Discovery Protocol (LLDP)" },
{ ETHERTYPE_3GPP2, "CDMA2000 A10 3GPP2 Packet" },
{ ETHERTYPE_TTE_PCF, "TTEthernet Protocol Control Frame" },
{ ETHERTYPE_CESOETH, "Circuit Emulation Services over Ethernet (MEF8)" },
{ ETHERTYPE_LLTD, "Link Layer Topology Discovery (LLTD)" },
{ ETHERTYPE_WSMP, "(WAVE) Short Message Protocol (WSM)" },
{ ETHERTYPE_VMLAB, "VMware Lab Manager" },
{ ETHERTYPE_COBRANET, "Cirrus Cobranet Packet" },
{ ETHERTYPE_NSRP, "Juniper Netscreen Redundant Protocol" },
/*
* NDISWAN on Windows translates Ethernet frames from higher-level
* protocols into PPP frames to hand to the PPP driver, and translates
* PPP frames from the PPP driver to hand to the higher-level protocols.
*
* Apparently the PPP driver, on at least some versions of Windows,
* passes frames for internal-to-PPP protocols up through NDISWAN;
* the protocol type field appears to be passed through unchanged
* (unlike what's done with, for example, the protocol type field
* for IP, which is mapped from its PPP value to its Ethernet value).
*
* This means that we may see, on Ethernet captures, frames for
* protocols internal to PPP, so we list as "Ethernet" protocol
* types the PPP protocol types we've seen.
*/
{ PPP_IPCP, "PPP IP Control Protocol" },
{ PPP_LCP, "PPP Link Control Protocol" },
{ PPP_PAP, "PPP Password Authentication Protocol" },
{ PPP_CCP, "PPP Compression Control Protocol" },
{ ETHERTYPE_LLT, "Veritas Low Latency Transport (not officially registered)" },
{ ETHERTYPE_CFM, "IEEE 802.1ag Connectivity Fault Management (CFM) protocol" },
{ ETHERTYPE_DCE, "Data Center Ethernet (DCE) protocol(Cisco)" },
{ ETHERTYPE_FCOE, "Fibre Channel over Ethernet" },
{ ETHERTYPE_IEEE80211_DATA_ENCAP, "IEEE 802.11 data encapsulation" },
{ ETHERTYPE_LINX, "LINX IPC Protocol" },
{ ETHERTYPE_FIP, "FCoE Initialization Protocol" },
{ ETHERTYPE_MIH, "Media Independent Handover Protocol" },
{ ETHERTYPE_ELMI, "Ethernet Local Management Interface (MEF16)" },
{ ETHERTYPE_PTP, "PTPv2 over Ethernet (IEEE1588)" },
{ ETHERTYPE_NCSI, "Network Controller Sideband Interface" },
{ ETHERTYPE_PRP, "Parallel Redundancy Protocol (PRP) and HSR Supervision (IEC62439 Part 3)" },
{ ETHERTYPE_FLIP, "Flow Layer Internal Protocol" },
{ ETHERTYPE_ROCE, "RDMA over Converged Ethernet" },
{ ETHERTYPE_TDMOE, "Digium TDM over Ethernet Protocol" },
{ ETHERTYPE_WAI, "WAI Authentication Protocol" },
{ ETHERTYPE_VNTAG, "VN-Tag" },
{ ETHERTYPE_SEL_L2, "Schweitzer Engineering Labs Layer 2 Protocol" },
{ ETHERTYPE_HSR, "High-availability Seamless Redundancy (IEC62439 Part 3)" },
{ ETHERTYPE_BPQ, "AX.25" },
{ ETHERTYPE_CMD, "CiscoMetaData" },
{ ETHERTYPE_XIP, "eXpressive Internet Protocol" },
{ ETHERTYPE_NWP, "Neighborhood Watch Protocol" },
{ ETHERTYPE_BLUECOM, "bluecom Protocol" },
{ ETHERTYPE_QINQ_OLD, "QinQ: old non-standard 802.1ad" },
{ 0, NULL }
};
/* ARP / RARP structs and definitions */
#ifndef ARPOP_REQUEST
#define ARPOP_REQUEST 1 /* ARP request. */
#endif
#ifndef ARPOP_REPLY
#define ARPOP_REPLY 2 /* ARP reply. */
#endif
/* Some OSes have different names, or don't define these at all */
#ifndef ARPOP_RREQUEST
#define ARPOP_RREQUEST 3 /* RARP request. */
#endif
#ifndef ARPOP_RREPLY
#define ARPOP_RREPLY 4 /* RARP reply. */
#endif
/*Additional parameters as per http://www.iana.org/assignments/arp-parameters*/
#ifndef ARPOP_DRARPREQUEST
#define ARPOP_DRARPREQUEST 5 /* DRARP request. */
#endif
#ifndef ARPOP_DRARPREPLY
#define ARPOP_DRARPREPLY 6 /* DRARP reply. */
#endif
#ifndef ARPOP_DRARPERROR
#define ARPOP_DRARPERROR 7 /* DRARP error. */
#endif
#ifndef ARPOP_IREQUEST
#define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
#endif
#ifndef ARPOP_IREPLY
#define ARPOP_IREPLY 9 /* Inverse ARP reply. */
#endif
#ifndef ATMARPOP_NAK
#define ATMARPOP_NAK 10 /* ATMARP NAK. */
#endif
/*Additional parameters as per http://www.iana.org/assignments/arp-parameters*/
#ifndef ARPOP_MARS_REQUEST
#define ARPOP_MARS_REQUEST 11 /*MARS request message. */
#endif
#ifndef ARPOP_MARS_MULTI
#define ARPOP_MARS_MULTI 12 /*MARS-Multi message. */
#endif
#ifndef ARPOP_MARS_MSERV
#define ARPOP_MARS_MSERV 13 /*MARS-Mserv message. */
#endif
#ifndef ARPOP_MARS_JOIN
#define ARPOP_MARS_JOIN 14 /*MARS-Join request. */
#endif
#ifndef ARPOP_MARS_LEAVE
#define ARPOP_MARS_LEAVE 15 /*MARS Leave request. */
#endif
#ifndef ARPOP_MARS_NAK
#define ARPOP_MARS_NAK 16 /*MARS nak message.*/
#endif
#ifndef ARPOP_MARS_UNSERV
#define ARPOP_MARS_UNSERV 17 /*MARS Unserv message. */
#endif
#ifndef ARPOP_MARS_SJOIN
#define ARPOP_MARS_SJOIN 18 /*MARS Sjoin message. */
#endif
#ifndef ARPOP_MARS_SLEAVE
#define ARPOP_MARS_SLEAVE 19 /*MARS Sleave message. */
#endif
#ifndef ARPOP_MARS_GROUPLIST_REQUEST
#define ARPOP_MARS_GROUPLIST_REQUEST 20 /*MARS Grouplist request message. */
#endif
#ifndef ARPOP_MARS_GROUPLIST_REPLY
#define ARPOP_MARS_GROUPLIST_REPLY 21 /*MARS Grouplist reply message. */
#endif
#ifndef ARPOP_MARS_REDIRECT_MAP
#define ARPOP_MARS_REDIRECT_MAP 22 /*MARS Grouplist request message. */
#endif
#ifndef ARPOP_MAPOS_UNARP
#define ARPOP_MAPOS_UNARP 23 /*MAPOS UNARP*/
#endif
#ifndef ARPOP_EXP1
#define ARPOP_EXP1 24 /* Experimental 1 */
#endif
#ifndef ARPOP_EXP2
#define ARPOP_EXP2 25 /* Experimental 2 */
#endif
#ifndef ARPOP_RESERVED1
#define ARPOP_RESERVED1 0 /*Reserved opcode 1*/
#endif
#ifndef ARPOP_RESERVED2
#define ARPOP_RESERVED2 65535 /*Reserved opcode 2*/
#endif
#ifndef DRARPERR_RESTRICTED
#define DRARPERR_RESTRICTED 1
#endif
#ifndef DRARPERR_NOADDRESSES
#define DRARPERR_NOADDRESSES 2
#endif
#ifndef DRARPERR_SERVERDOWN
#define DRARPERR_SERVERDOWN 3
#endif
#ifndef DRARPERR_MOVED
#define DRARPERR_MOVED 4
#endif
#ifndef DRARPERR_FAILURE
#define DRARPERR_FAILURE 5
#endif
static const value_string op_vals[] = {
{ ARPOP_REQUEST, "request" },
{ ARPOP_REPLY, "reply" },
{ ARPOP_RREQUEST, "reverse request" },
{ ARPOP_RREPLY, "reverse reply" },
{ ARPOP_DRARPREQUEST, "drarp request" },
{ ARPOP_DRARPREPLY, "drarp reply" },
{ ARPOP_DRARPERROR, "drarp error" },
{ ARPOP_IREQUEST, "inverse request" },
{ ARPOP_IREPLY, "inverse reply" },
{ ATMARPOP_NAK, "arp nak" },
{ ARPOP_MARS_REQUEST, "mars request" },
{ ARPOP_MARS_MULTI, "mars multi" },
{ ARPOP_MARS_MSERV, "mars mserv" },
{ ARPOP_MARS_JOIN, "mars join" },
{ ARPOP_MARS_LEAVE, "mars leave" },
{ ARPOP_MARS_NAK, "mars nak" },
{ ARPOP_MARS_UNSERV, "mars unserv" },
{ ARPOP_MARS_SJOIN, "mars sjoin" },
{ ARPOP_MARS_SLEAVE, "mars sleave" },
{ ARPOP_MARS_GROUPLIST_REQUEST, "mars grouplist request" },
{ ARPOP_MARS_GROUPLIST_REPLY, "mars gruoplist reply" },
{ ARPOP_MARS_REDIRECT_MAP, "mars redirect map" },
{ ARPOP_MAPOS_UNARP, "mapos unarp" },
{ ARPOP_EXP1, "experimental 1" },
{ ARPOP_EXP2, "experimental 2" },
{ ARPOP_RESERVED1, "reserved" },
{ ARPOP_RESERVED2, "reserved" },
{ 0, NULL } };
static const char* get_arp_hardware_type_string(gushort type);
static const char* get_arp_protocol_type_string(gushort type);
static const char* get_arp_optcode_type_string(gushort type);
static gboolean buf_to_mac_addr(const char* psz_buf, int buf_len, /*INOUT*/char* psz_rc, int rc_len);
static gboolean buf_to_ip(const char* psz_buf, int buf_len, /*INOUT*/char* psz_rc, int rc_len);
static int dissect_proc_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_);
void proto_register_foo(void)
{
protocol_handle_foo = proto_register_protocol(
PROTOCOL_FULL_NAME_FOO,
PROTOCOL_SHORT_NAME_FOO,
PROTOCOL_DISPLAY_FILTER_NAME_FOO);
proto_register_field_array(protocol_handle_foo, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
dissector_handle_foo = register_dissector(PROTOCOL_SHORT_NAME_FOO, dissect_proc_foo, protocol_handle_foo);
}
void proto_reg_handoff_foo(void)
{
// 只有注册了协议分析器要处理的协议, wireshark才会回调到dissector_handle_foo
dissector_add_uint("ethertype", ETHERTYPE_ARP, dissector_handle_foo);
// dissector_add_uint("ethertype", ETHERTYPE_REVARP, dissector_handle_foo);
}
// https://stackoverflow.com/questions/20247551/icmp-echo-checksum
// http://www.faqs.org/rfcs/rfc1071.html
static guint16 calc_check_sum(const guint8* data, int len)
{
guint32 sum = 0;
guint16 tmp = 0;
int i = 0;
do {
if ((NULL == data) || (len <= 0) || (0 != (len % 8))) {
break;
}
for (i = 0; i < len; i += 2) {
tmp = (guint16)g_ntohs(*(guint16*)(data + i)); // BE data
if (0 == i) {
sum = tmp;
continue;
}
else if (2 == i) {
// this is check sum, need skip it
continue;
}
else {
sum += tmp;
}
}
// add carry bit !
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
};
sum = ~sum;
} while (0);
return (guint16)sum;
}
// wireshark工程由vs2015编译器设置成默认字节对齐(8字节)
// Projects-Properties-Configuration Properties-C/C++-Code generation-Struct Member Alignment, 如果没有修改过,则默认值是Default,即8字节对齐。
typedef struct _tag_arp_header {
// these data type all BE
gushort hardware_type; // Hardware type : Ethernet(1)
gushort protocol_type; // Protocol type: IPv4 (0x0800)
guchar hardware_size; // Hardware size: 6
guchar protocol_size; // Protocol size: 4
gushort opt_code; // Opcode: request (1)
} TAG_ARP_HEADER;
static int dissect_proc_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_)
{
bool b_pasre_ok = false;
TAG_ARP_HEADER hdr_arp;
char sz_buf[4096] = { '\0' };
proto_item* item = NULL;
proto_item* item_tmp = NULL;
proto_tree* sub_tree_foo = NULL;
guint captured_length = tvb_captured_length(tvb);
guint data_len_left = captured_length; // 要处理的数据长度
guint data_offset = 0; // 从起始数据开始偏移多少
const guint8* data_left = NULL; // 要处理的数据
const guint8* data_org = NULL; // 要处理的原始数据
guint16 tmp_u16 = 0;
// set col.5 = "Protocol" 's content to 'foo'
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
// set col.7 = "Info" 's content to empty, else will display by tcp info
col_clear(pinfo->cinfo, COL_INFO);
item = proto_tree_add_item(tree, protocol_handle_foo, tvb, 0, -1, ENC_NA);
do {
// 在节点下增加子树, 此时子树还没有显示出来
sub_tree_foo = proto_item_add_subtree(item, ett_foo);
if (NULL == sub_tree_foo) {
break;
}
// save data and data len
data_org = tvb_get_ptr(tvb, 0, -1);
data_left = data_org;
data_offset = 0;
// ready read header
if (data_len_left < sizeof(TAG_ARP_HEADER)) {
break;
}
memcpy(&hdr_arp, data_left, sizeof(TAG_ARP_HEADER));
data_left += sizeof(TAG_ARP_HEADER);
data_len_left -= sizeof(TAG_ARP_HEADER);
data_offset += sizeof(TAG_ARP_HEADER);
// show hdr_arp.hardware_type
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
offsetof(TAG_ARP_HEADER, hardware_type), sizeof(hdr_arp.hardware_type),
NULL, // 可选
NULL,
-1);
tmp_u16 = g_ntohs(hdr_arp.hardware_type);
proto_item_set_text(item_tmp, "TAG_ARP_HEADER.hardware_type = %s (0x%4.4X)", get_arp_hardware_type_string(tmp_u16), tmp_u16);
// show hdr_arp.protocol_type
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
offsetof(TAG_ARP_HEADER, protocol_type), sizeof(hdr_arp.protocol_type),
NULL, // 可选
NULL,
-1);
tmp_u16 = g_ntohs(hdr_arp.protocol_type);
proto_item_set_text(item_tmp, "TAG_ARP_HEADER.protocol_type = %s (0x%4.4X)", get_arp_protocol_type_string(tmp_u16), tmp_u16);
// show hdr_arp.hardware_size
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
offsetof(TAG_ARP_HEADER, hardware_size), sizeof(hdr_arp.hardware_size),
NULL, // 可选
NULL,
-1);
tmp_u16 = hdr_arp.hardware_size;
proto_item_set_text(item_tmp, "TAG_ARP_HEADER.hardware_size = %d", tmp_u16);
// show hdr_arp.protocol_size
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
offsetof(TAG_ARP_HEADER, protocol_size), sizeof(hdr_arp.protocol_size),
NULL, // 可选
NULL,
-1);
tmp_u16 = hdr_arp.protocol_size;
proto_item_set_text(item_tmp, "TAG_ARP_HEADER.protocol_size = %d", tmp_u16);
// show hdr_arp.opt_code
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
offsetof(TAG_ARP_HEADER, opt_code), sizeof(hdr_arp.opt_code),
NULL, // 可选
NULL,
-1);
tmp_u16 = g_ntohs(hdr_arp.opt_code);
proto_item_set_text(item_tmp, "TAG_ARP_HEADER.opt_code = %s (0x%4.4X)", get_arp_optcode_type_string(tmp_u16), tmp_u16);
tmp_u16 = (hdr_arp.hardware_size + hdr_arp.protocol_size) * 2;
if (data_len_left < (tmp_u16)) {
break;
}
// show sender mac
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
data_offset, hdr_arp.hardware_size,
NULL, // 可选
NULL,
-1);
memset(sz_buf, 0, sizeof(sz_buf));
buf_to_mac_addr(data_left, hdr_arp.hardware_size, sz_buf, sizeof(sz_buf));
data_left += hdr_arp.hardware_size;
data_len_left -= hdr_arp.hardware_size;
data_offset += hdr_arp.hardware_size;
proto_item_set_text(item_tmp, "sender mac = %s", sz_buf);
// show send ip
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
data_offset, hdr_arp.protocol_size,
NULL, // 可选
NULL,
-1);
memset(sz_buf, 0, sizeof(sz_buf));
buf_to_ip(data_left, hdr_arp.protocol_size, sz_buf, sizeof(sz_buf));
data_left += hdr_arp.protocol_size;
data_len_left -= hdr_arp.protocol_size;
data_offset += hdr_arp.protocol_size;
proto_item_set_text(item_tmp, "sender ip = %s", sz_buf);
// show request mac
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
data_offset, hdr_arp.hardware_size,
NULL, // 可选
NULL,
-1);
memset(sz_buf, 0, sizeof(sz_buf));
buf_to_mac_addr(data_left, hdr_arp.hardware_size, sz_buf, sizeof(sz_buf));
data_left += hdr_arp.hardware_size;
data_len_left -= hdr_arp.hardware_size;
data_offset += hdr_arp.hardware_size;
proto_item_set_text(item_tmp, "request mac = %s", sz_buf);
// show request ip
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb,
data_offset, hdr_arp.protocol_size,
NULL, // 可选
NULL,
-1);
memset(sz_buf, 0, sizeof(sz_buf));
buf_to_ip(data_left, hdr_arp.protocol_size, sz_buf, sizeof(sz_buf));
data_left += hdr_arp.protocol_size;
data_len_left -= hdr_arp.protocol_size;
data_offset += hdr_arp.protocol_size;
proto_item_set_text(item_tmp, "request ip = %s", sz_buf);
b_pasre_ok = true;
} while (0);
if (NULL != sub_tree_foo) {
// show END message, parse ok or error
item_tmp = proto_tree_add_string_format_value(sub_tree_foo, hf_foo_message, tvb, 0, -1,
NULL, // 可选
NULL,
-1);
proto_item_set_text(item_tmp, b_pasre_ok ? "nice, parse ok" : "error, please connect developer");
}
return captured_length; // return data length by process
}
static const char* get_arp_hardware_type_string(gushort type)
{
int i = 0;
int ary_size = sizeof(arp_hrd_vals) / sizeof(arp_hrd_vals[0]);
const char* rc = NULL;
for (i = 0; i < ary_size; i++) {
if (type == arp_hrd_vals[i].value) {
rc = arp_hrd_vals[i].strptr;
break;
}
}
if (NULL == rc) {
rc = "unknown";
}
return rc;
}
static const char* get_arp_protocol_type_string(gushort type)
{
int i = 0;
int ary_size = sizeof(my_etype_vals) / sizeof(my_etype_vals[0]);
const char* rc = NULL;
for (i = 0; i < ary_size; i++) {
if (type == my_etype_vals[i].value) {
rc = my_etype_vals[i].strptr;
break;
}
}
if (NULL == rc) {
rc = "unknown";
}
return rc;
}
static const char* get_arp_optcode_type_string(gushort type)
{
int i = 0;
int ary_size = sizeof(op_vals) / sizeof(op_vals[0]);
const char* rc = NULL;
for (i = 0; i < ary_size; i++) {
if (type == op_vals[i].value) {
rc = op_vals[i].strptr;
break;
}
}
if (NULL == rc) {
rc = "unknown";
}
return rc;
}
static gboolean buf_to_mac_addr(const char* psz_buf, int buf_len, /*INOUT*/char* psz_rc, int rc_len)
{
gboolean rc = FALSE;
int i = 0;
char buf[4] = { '\0' };
guchar tmp_uc = 0;
do {
if ((NULL == psz_buf)
|| (NULL == psz_rc)
|| (rc_len < (buf_len * 2 + buf_len - 1))) {
break;
}
memset(psz_rc, 0, rc_len);
for (i = 0; i < buf_len; i++) {
memset(buf, 0, sizeof(buf));
tmp_uc = *(psz_buf + i);
sprintf(buf, "%2.2X", tmp_uc);
strcat(psz_rc, buf);
if (i != (buf_len - 1)) {
strcat(psz_rc, ":");
}
}
} while (0);
return rc;
}
static gboolean buf_to_ip(const char* psz_buf, int buf_len, /*INOUT*/char* psz_rc, int rc_len)
{
gboolean rc = FALSE;
int i = 0;
char buf[4] = { '\0' };
guchar tmp_uc = 0;
do {
if ((NULL == psz_buf)
|| (NULL == psz_rc)
|| (rc_len < (buf_len * 3 + buf_len - 1))) {
break;
}
memset(psz_rc, 0, rc_len);
for (i = 0; i < buf_len; i++) {
memset(buf, 0, sizeof(buf));
tmp_uc = *(psz_buf + i);
sprintf(buf, "%d", tmp_uc);
strcat(psz_rc, buf);
if (i != (buf_len - 1)) {
strcat(psz_rc, ".");
}
}
} while (0);
return rc;
}