2011-11-08 17:36:12 +00:00
/* packet-vxlan.c
*
* Routines for Virtual eXtensible Local Area Network ( VXLAN ) packet dissection
2016-01-17 02:41:07 +00:00
* RFC 7348 plus draft - smith - vxlan - group - policy - 01
2011-11-08 17:36:12 +00:00
*
2016-07-02 19:34:37 +00:00
* ( c ) Copyright 2016 , Sumit Kumar Jha < sjha3 @ ncsu . edu >
* Support for VXLAN GPE ( https : //www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-02.txt)
*
2011-11-08 17:36:12 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* 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
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2011-11-08 17:36:12 +00:00
*/
2012-09-20 02:03:38 +00:00
# include "config.h"
2011-11-08 17:36:12 +00:00
# include <epan/packet.h>
2015-07-07 08:46:34 +00:00
# include <epan/tfs.h>
2016-07-19 07:41:33 +00:00
# include "packet-vxlan.h"
2011-11-08 17:36:12 +00:00
2014-03-12 10:07:10 +00:00
# define UDP_PORT_VXLAN 4789
2016-07-02 19:34:37 +00:00
# define UDP_PORT_VXLAN_GPE 4790
2014-03-12 10:07:10 +00:00
2013-12-10 19:50:20 +00:00
void proto_register_vxlan ( void ) ;
void proto_reg_handoff_vxlan ( void ) ;
2011-11-08 17:36:12 +00:00
static int proto_vxlan = - 1 ;
2016-07-12 13:09:57 +00:00
static int proto_vxlan_gpe = - 1 ;
2011-11-08 17:36:12 +00:00
static int hf_vxlan_flags = - 1 ;
2016-07-02 19:34:37 +00:00
static int hf_vxlan_gpe_flags = - 1 ;
2015-07-07 08:46:34 +00:00
static int hf_vxlan_flags_reserved = - 1 ;
2016-07-02 19:34:37 +00:00
static int hf_vxlan_reserved_8 = - 1 ;
2015-07-07 08:46:34 +00:00
static int hf_vxlan_flag_a = - 1 ;
static int hf_vxlan_flag_d = - 1 ;
2011-11-08 17:36:12 +00:00
static int hf_vxlan_flag_i = - 1 ;
2015-07-07 08:46:34 +00:00
static int hf_vxlan_flag_g = - 1 ;
static int hf_vxlan_gbp = - 1 ;
2011-11-08 17:36:12 +00:00
static int hf_vxlan_vni = - 1 ;
2016-07-02 19:34:37 +00:00
static int hf_vxlan_gpe_flag_i = - 1 ;
static int hf_vxlan_gpe_flag_p = - 1 ;
static int hf_vxlan_gpe_flag_o = - 1 ;
static int hf_vxlan_gpe_flag_ver = - 1 ;
static int hf_vxlan_gpe_flag_reserved = - 1 ;
static int hf_vxlan_gpe_reserved_16 = - 1 ;
static int hf_vxlan_next_proto = - 1 ;
2011-11-08 17:36:12 +00:00
static int ett_vxlan = - 1 ;
2016-07-02 19:34:37 +00:00
static int ett_vxlan_flags = - 1 ;
2011-11-08 17:36:12 +00:00
2015-07-07 08:46:34 +00:00
static const int * flags_fields [ ] = {
& hf_vxlan_flag_g ,
& hf_vxlan_flag_d ,
& hf_vxlan_flag_i ,
& hf_vxlan_flag_a ,
& hf_vxlan_flags_reserved ,
NULL
} ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
static const int * gpe_flags_fields [ ] = {
& hf_vxlan_gpe_flag_ver ,
& hf_vxlan_gpe_flag_i ,
& hf_vxlan_gpe_flag_p ,
& hf_vxlan_gpe_flag_o ,
& hf_vxlan_gpe_flag_reserved ,
NULL
} ;
static const value_string vxlan_next_protocols [ ] = {
{ VXLAN_IPV4 , " IPv4 " } ,
{ VXLAN_IPV6 , " IPv6 " } ,
{ VXLAN_ETHERNET , " Ethernet " } ,
{ VXLAN_NSH , " Network Service Header " } ,
{ VXLAN_MPLS , " MPLS " } ,
{ 0 , NULL }
} ;
2011-11-08 17:36:12 +00:00
static dissector_handle_t eth_handle ;
2016-07-02 19:34:37 +00:00
static dissector_table_t vxlan_dissector_table ;
2011-11-08 17:36:12 +00:00
2015-11-18 01:16:06 +00:00
static int
2016-07-02 19:34:37 +00:00
dissect_vxlan_common ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , int is_gpe )
2011-11-08 17:36:12 +00:00
{
2015-07-10 12:26:10 +00:00
proto_tree * vxlan_tree ;
proto_item * ti ;
2011-11-09 02:48:51 +00:00
tvbuff_t * next_tvb ;
int offset = 0 ;
2016-07-19 07:41:33 +00:00
guint32 vxlan_next_proto ;
2011-11-08 17:36:12 +00:00
2011-11-09 02:48:51 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " VxLAN " ) ;
col_clear ( pinfo - > cinfo , COL_INFO ) ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
ti = proto_tree_add_item ( tree , proto_vxlan , tvb , offset , 8 , ENC_NA ) ;
2011-11-09 02:48:51 +00:00
vxlan_tree = proto_item_add_subtree ( ti , ett_vxlan ) ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
if ( is_gpe ) {
proto_tree_add_bitmask ( vxlan_tree , tvb , offset , hf_vxlan_gpe_flags , ett_vxlan_flags , gpe_flags_fields , ENC_BIG_ENDIAN ) ;
offset + = 1 ;
proto_tree_add_item ( vxlan_tree , hf_vxlan_gpe_reserved_16 , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
2016-07-19 07:41:33 +00:00
proto_tree_add_item_ret_uint ( vxlan_tree , hf_vxlan_next_proto , tvb , offset , 1 , ENC_BIG_ENDIAN , & vxlan_next_proto ) ;
2016-07-02 19:34:37 +00:00
offset + = 1 ;
} else {
proto_tree_add_bitmask ( vxlan_tree , tvb , offset , hf_vxlan_flags , ett_vxlan_flags , flags_fields , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
2011-11-08 17:36:12 +00:00
2016-07-02 19:34:37 +00:00
proto_tree_add_item ( vxlan_tree , hf_vxlan_gbp , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
}
2011-11-08 17:36:12 +00:00
2011-11-09 02:48:51 +00:00
proto_tree_add_item ( vxlan_tree , hf_vxlan_vni , tvb , offset , 3 , ENC_BIG_ENDIAN ) ;
2016-07-02 19:34:37 +00:00
offset + = 3 ;
2011-11-08 17:36:12 +00:00
2011-11-09 02:48:51 +00:00
proto_tree_add_item ( vxlan_tree , hf_vxlan_reserved_8 , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2016-07-02 19:34:37 +00:00
offset + = 1 ;
2011-11-09 02:48:51 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , offset ) ;
2016-07-02 19:34:37 +00:00
if ( is_gpe ) {
2016-07-19 07:41:33 +00:00
if ( ! dissector_try_uint ( vxlan_dissector_table , vxlan_next_proto , next_tvb , pinfo , tree ) ) {
call_data_dissector ( next_tvb , pinfo , vxlan_tree ) ;
2016-07-02 19:34:37 +00:00
}
} else {
call_dissector ( eth_handle , next_tvb , pinfo , tree ) ;
}
2011-11-08 17:36:12 +00:00
2015-11-18 01:16:06 +00:00
return tvb_captured_length ( tvb ) ;
2011-11-08 17:36:12 +00:00
}
2016-07-02 19:34:37 +00:00
static int
dissect_vxlan_gpe ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
return dissect_vxlan_common ( tvb , pinfo , tree , TRUE ) ;
}
static int
dissect_vxlan ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
return dissect_vxlan_common ( tvb , pinfo , tree , FALSE ) ;
}
2011-11-08 17:36:12 +00:00
/* Register VxLAN with Wireshark */
void
proto_register_vxlan ( void )
{
2011-11-09 02:48:51 +00:00
static hf_register_info hf [ ] = {
{ & hf_vxlan_flags ,
{ " Flags " , " vxlan.flags " ,
2015-07-07 08:46:34 +00:00
FT_UINT16 , BASE_HEX , NULL , 0x00 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_flags ,
{ " Flags " , " vxlan.flags " ,
FT_UINT8 , BASE_HEX , NULL , 0x00 ,
NULL , HFILL
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flags_reserved ,
{ " Reserved(R) " , " vxlan.flags_reserved " ,
FT_BOOLEAN , 16 , NULL , 0x77b7 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_flag_reserved ,
{ " Reserved(R) " , " vxlan.flags_reserved " ,
FT_UINT8 , BASE_DEC , NULL , 0xC2 ,
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flag_g ,
{ " GBP Extension " , " vxlan.flag_g " ,
FT_BOOLEAN , 16 , TFS ( & tfs_defined_not_defined ) , 0x8000 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_flag_i ,
2015-07-07 08:46:34 +00:00
{ " VXLAN Network ID (VNI) " , " vxlan.flag_i " ,
FT_BOOLEAN , 16 , NULL , 0x0800 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flag_d ,
{ " Don't Learn " , " vxlan.flag_d " ,
FT_BOOLEAN , 16 , NULL , 0x0040 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_flag_a ,
{ " Policy Applied " , " vxlan.flag_a " ,
FT_BOOLEAN , 16 , NULL , 0x0008 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL ,
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_flag_ver ,
{ " Version " , " vxlan.ver " ,
FT_UINT8 , BASE_DEC , NULL , 0x30 ,
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_gpe_flag_i ,
{ " Instance " , " vxlan.i_bit " ,
FT_UINT8 , BASE_DEC , NULL , 0x08 ,
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_gpe_flag_p ,
{ " Next Protocol Bit " , " vxlan.p_bit " ,
FT_UINT8 , BASE_DEC , NULL , 0x04 ,
NULL , HFILL ,
} ,
} ,
{ & hf_vxlan_gpe_flag_o ,
{ " OAM bit " , " vxlan.o_bit " ,
FT_UINT8 , BASE_DEC , NULL , 0x01 ,
NULL , HFILL ,
} ,
} ,
2015-07-07 08:46:34 +00:00
{ & hf_vxlan_gbp ,
{ " Group Policy ID " , " vxlan.gbp " ,
FT_UINT16 , BASE_DEC , NULL , 0x00 ,
2011-11-09 02:48:51 +00:00
NULL , HFILL
} ,
} ,
{ & hf_vxlan_vni ,
{ " VXLAN Network Identifier (VNI) " , " vxlan.vni " ,
FT_UINT24 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL
} ,
} ,
{ & hf_vxlan_reserved_8 ,
{ " Reserved " , " vxlan.reserved8 " ,
FT_UINT8 , BASE_DEC , NULL , 0x00 ,
NULL , HFILL
} ,
} ,
2016-07-02 19:34:37 +00:00
{ & hf_vxlan_gpe_reserved_16 ,
{ " Reserved " , " vxlan.reserved_16 " ,
FT_UINT16 , BASE_DEC , NULL , 0x0000 ,
NULL , HFILL
} ,
} ,
{ & hf_vxlan_next_proto ,
{ " Next Protocol " , " vxlan.next_proto " ,
FT_UINT8 , BASE_DEC , VALS ( vxlan_next_protocols ) , 0x00 ,
NULL , HFILL
} ,
} ,
2011-11-09 02:48:51 +00:00
} ;
/* Setup protocol subtree array */
static gint * ett [ ] = {
& ett_vxlan ,
2016-07-02 19:34:37 +00:00
& ett_vxlan_flags ,
2011-11-09 02:48:51 +00:00
} ;
/* Register the protocol name and description */
2016-07-12 13:09:57 +00:00
proto_vxlan = proto_register_protocol ( " Virtual eXtensible Local Area Network " , " VXLAN " , " vxlan " ) ;
/* Protocol registered just for Decode As */
proto_vxlan_gpe = proto_register_protocol ( " Virtual eXtensible Local Area Network (GPE) " , " VXLAN (GPE) " , " vxlan_gpe " ) ;
2011-11-09 02:48:51 +00:00
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array ( proto_vxlan , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2016-07-02 19:34:37 +00:00
vxlan_dissector_table = register_dissector_table ( " vxlan.next_proto " , " VXLAN Next Protocol " , proto_vxlan , FT_UINT8 , BASE_DEC , DISSECTOR_TABLE_ALLOW_DUPLICATE ) ;
2011-11-08 17:36:12 +00:00
}
void
proto_reg_handoff_vxlan ( void )
{
dissector_handle_t vxlan_handle ;
2016-07-02 19:34:37 +00:00
dissector_handle_t vxlan_gpe_handle ;
2011-11-08 17:36:12 +00:00
2016-01-17 02:41:07 +00:00
/*
* RFC 7348 Figures 1 and 2 , in the Payload section , say
*
* " (Note that the original Ethernet Frame's FCS is not included) "
*
* meaning that the inner Ethernet frame does * not * include an
* FCS .
*/
2016-03-16 13:02:52 +00:00
eth_handle = find_dissector_add_dependency ( " eth_withoutfcs " , proto_vxlan ) ;
2011-11-08 17:36:12 +00:00
2015-12-09 03:49:44 +00:00
vxlan_handle = create_dissector_handle ( dissect_vxlan , proto_vxlan ) ;
2016-07-12 13:09:57 +00:00
vxlan_gpe_handle = create_dissector_handle ( dissect_vxlan_gpe , proto_vxlan_gpe ) ;
2014-03-12 10:07:10 +00:00
dissector_add_uint ( " udp.port " , UDP_PORT_VXLAN , vxlan_handle ) ;
2016-07-02 19:34:37 +00:00
dissector_add_uint ( " udp.port " , UDP_PORT_VXLAN_GPE , vxlan_gpe_handle ) ;
2011-11-08 17:36:12 +00:00
}
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 8 expandtab :
* : indentSize = 4 : tabSize = 8 : noTabs = true :
*/