/* packet-lisp.c * Routines for Locator/ID Separation Protocol (LISP) Control Message dissection * Copyright 2011, 2014 Lorand Jakab * * Geo Coordinates LCAF dissection based on previous work by Radu Terciu * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include "packet-lisp.h" #include #include #include #include #include void proto_register_lisp(void); void proto_reg_handoff_lisp(void); /* * See RFC 6830 "Locator/ID Separation Protocol (LISP)", * draft-ietf-lisp-lcaf-05 "LISP Canonical Address Format (LCAF)", * draft-ietf-lisp-vendor-lcaf-07 "Vendor Specific LISP Canonical Address Format (LCAF)" * draft-ietf-lisp-sec-04 "LISP-Security (LISP-SEC)", * draft-ermagan-lisp-nat-traversal-03 "NAT traversal for LISP", * draft-farinacci-lisp-name-encoding-09 "LISP Distinguished Name Encoding" * for packet format and protocol information. */ /* LISP Control Message types */ #define LISP_MAP_REQUEST 1 #define LISP_MAP_REPLY 2 #define LISP_MAP_REGISTER 3 #define LISP_MAP_NOTIFY 4 #define LISP_MAP_REFERRAL 6 #define LISP_INFO 7 #define LISP_ECM 8 #define LISP_ACT_NONE 0 #define LISP_ACT_FWD_NATIVE 1 #define LISP_ACT_MREQ 2 #define LISP_ACT_DROP 3 #define LISP_ACT_DROP_PD 4 #define LISP_ACT_DROP_AF 5 #define LISP_ACT_FWD_UA 6 #define DDT_NODE_REF 0 #define DDT_MS_REF 1 #define DDT_MS_ACK 2 #define DDT_MS_NREG 3 #define DDT_DLGT_HOLE 4 #define DDT_NAUTH 5 #define LCAF_NULL 0 #define LCAF_AFI_LIST 1 #define LCAF_IID 2 #define LCAF_ASN 3 #define LCAF_APP_DATA 4 #define LCAF_GEO 5 #define LCAF_OKEY 6 #define LCAF_NATT 7 #define LCAF_NONCE_LOC 8 #define LCAF_MCAST_INFO 9 #define LCAF_ELP 10 #define LCAF_SEC_KEY 11 #define LCAF_SRC_DST_KEY 12 #define LCAF_RLE 13 #define LCAF_JSON 14 #define LCAF_KV_ADDR_PAIR 15 #define LCAF_VENDOR 255 #define LCAF_HEADER_LEN 6 #define LISP_ECM_HEADER_LEN 4 #define LISP_MAP_ACT 0xE000 #define LISP_MAP_AUTH 0x1000 #define REFERRAL_INCOMPLETE 0x0800 #define LOCAL_BIT_MASK 0x0004 #define PROBE_BIT_MASK 0x0002 #define REACH_BIT_MASK 0x0001 #define MAP_REQ_FLAG_A 0x080000 #define MAP_REQ_FLAG_M 0x040000 #define MAP_REQ_FLAG_P 0x020000 #define MAP_REQ_FLAG_S 0x010000 #define MAP_REQ_FLAG_p 0x008000 #define MAP_REQ_FLAG_s 0x004000 #define MAP_REQ_RESERVED 0x003FE0 #define MAP_REP_FLAG_P 0x080000 #define MAP_REP_FLAG_E 0x040000 #define MAP_REP_FLAG_S 0x020000 #define MAP_REP_RESERVED 0x01FFFF #define MAP_REG_FLAG_P 0x080000 #define MAP_REG_FLAG_S 0x040000 #define MAP_REG_FLAG_I 0x020000 #define MAP_REG_FLAG_R 0x010000 #define MAP_REG_RESERVED 0x00FFFE #define MAP_REG_FLAG_M 0x000001 #define MAP_NOT_FLAG_I 0x080000 #define MAP_NOT_FLAG_R 0x040000 #define MAP_NOT_RESERVED 0x03FFFF #define MAP_REF_RESERVED 0x0FFFFF #define INFO_FLAG_R 0x080000 #define INFO_RESERVED 0x07FFFFFF #define ECM_FLAG_S 0x08000000 #define ECM_FLAG_D 0x04000000 #define MCINFO_FLAG_R 0x04 #define MCINFO_FLAG_L 0x02 #define MCINFO_FLAG_J 0x01 #define ELP_FLAG_L 0x0004 #define ELP_FLAG_P 0x0002 #define ELP_FLAG_S 0x0001 /* Initialize the protocol and registered fields */ static int proto_lisp = -1; static int hf_lisp_type = -1; static int hf_lisp_irc = -1; static int hf_lisp_records = -1; static int hf_lisp_nonce = -1; static int hf_lisp_keyid = -1; static int hf_lisp_authlen = -1; static int hf_lisp_auth = -1; static int hf_lisp_msrtr_keyid = -1; static int hf_lisp_msrtr_authlen = -1; static int hf_lisp_msrtr_auth = -1; static int hf_lisp_xtrid = -1; static int hf_lisp_siteid = -1; /* Map-Request fields */ static int hf_lisp_mreq_flags = -1; static int hf_lisp_mreq_flags_auth = -1; static int hf_lisp_mreq_flags_mrp = -1; static int hf_lisp_mreq_flags_probe = -1; static int hf_lisp_mreq_flags_smr = -1; static int hf_lisp_mreq_flags_pitr = -1; static int hf_lisp_mreq_flags_smri = -1; static int hf_lisp_mreq_res = -1; static int hf_lisp_mreq_srceid_afi = -1; static int hf_lisp_mreq_srceid_string = -1; static int hf_lisp_mreq_srceid_ipv4 = -1; static int hf_lisp_mreq_srceid_ipv6 = -1; static int hf_lisp_mreq_srceid_mac = -1; static int hf_lisp_mreq_itr_rloc = -1; static int hf_lisp_mreq_itr_rloc_afi = -1; static int hf_lisp_mreq_itr_rloc_ipv4 = -1; static int hf_lisp_mreq_itr_rloc_ipv6 = -1; static int hf_lisp_mreq_record = -1; static int hf_lisp_mreq_record_res = -1; static int hf_lisp_mreq_record_prefix_length = -1; static int hf_lisp_mreq_record_prefix_afi = -1; static int hf_lisp_mreq_record_prefix_ipv4 = -1; static int hf_lisp_mreq_record_prefix_ipv6 = -1; static int hf_lisp_mreq_record_prefix_mac = -1; static int hf_lisp_mreq_record_prefix_dn = -1; /* Map-Reply fields */ static int hf_lisp_mrep_record = -1; static int hf_lisp_mrep_flags_probe = -1; static int hf_lisp_mrep_flags_enlr = -1; static int hf_lisp_mrep_flags_sec = -1; static int hf_lisp_mrep_res = -1; /* Map-Register fields */ static int hf_lisp_mreg_flags_pmr = -1; static int hf_lisp_mreg_flags_sec = -1; static int hf_lisp_mreg_flags_xtrid = -1; static int hf_lisp_mreg_flags_rtr = -1; static int hf_lisp_mreg_flags_wmn = -1; static int hf_lisp_mreg_res = -1; /* Map-Notify fields */ static int hf_lisp_mnot_flags_xtrid = -1; static int hf_lisp_mnot_flags_rtr = -1; static int hf_lisp_mnot_res = -1; /* Map-Referral fields */ static int hf_lisp_mref_res = -1; static int hf_lisp_referral_sigcnt = -1; static int hf_lisp_referral_incomplete = -1; /* Info fields */ static int hf_lisp_info_r = -1; static int hf_lisp_info_res1 = -1; static int hf_lisp_info_ttl = -1; static int hf_lisp_info_res2 = -1; static int hf_lisp_info_prefix_masklen = -1; static int hf_lisp_info_prefix_afi = -1; static int hf_lisp_info_prefix_ipv4 = -1; static int hf_lisp_info_prefix_ipv6 = -1; static int hf_lisp_info_afi = -1; /* Mapping record fields */ static int hf_lisp_mapping = -1; static int hf_lisp_mapping_ttl = -1; static int hf_lisp_mapping_loccnt = -1; static int hf_lisp_mapping_eid_masklen = -1; static int hf_lisp_mapping_act = -1; static int hf_lisp_mapping_auth = -1; static int hf_lisp_mapping_res1 = -1; static int hf_lisp_mapping_res2 = -1; static int hf_lisp_mapping_ver = -1; static int hf_lisp_mapping_eid_afi = -1; static int hf_lisp_mapping_eid_ipv4 = -1; static int hf_lisp_mapping_eid_ipv6 = -1; static int hf_lisp_mapping_eid_mac = -1; static int hf_lisp_mapping_eid_dn = -1; /* Locator fields */ static int hf_lisp_loc = -1; static int hf_lisp_loc_priority = -1; static int hf_lisp_loc_weight = -1; static int hf_lisp_loc_mpriority = -1; static int hf_lisp_loc_mweight = -1; static int hf_lisp_loc_flags = -1; static int hf_lisp_loc_flags_local = -1; static int hf_lisp_loc_flags_probe = -1; static int hf_lisp_loc_flags_reach = -1; static int hf_lisp_loc_flags_res = -1; static int hf_lisp_loc_afi = -1; static int hf_lisp_loc_locator = -1; /* LCAF fields */ static int hf_lisp_lcaf = -1; static int hf_lisp_lcaf_header = -1; static int hf_lisp_lcaf_res1 = -1; static int hf_lisp_lcaf_flags = -1; static int hf_lisp_lcaf_type = -1; static int hf_lisp_lcaf_res2 = -1; static int hf_lisp_lcaf_length = -1; /* LCAF AFI List fields */ static int hf_lisp_lcaf_afi_list_item = -1; static int hf_lisp_lcaf_afi_list_afi = -1; static int hf_lisp_lcaf_afi_list_ipv4 = -1; static int hf_lisp_lcaf_afi_list_ipv6 = -1; static int hf_lisp_lcaf_afi_list_mac = -1; static int hf_lisp_lcaf_afi_list_dn = -1; /* LCAF IID fields */ static int hf_lisp_lcaf_iid = -1; static int hf_lisp_lcaf_iid_afi = -1; static int hf_lisp_lcaf_iid_ipv4 = -1; static int hf_lisp_lcaf_iid_ipv6 = -1; static int hf_lisp_lcaf_iid_mac = -1; static int hf_lisp_lcaf_iid_dn = -1; /* LCAF ASN fields */ static int hf_lisp_lcaf_asn = -1; static int hf_lisp_lcaf_asn_afi = -1; static int hf_lisp_lcaf_asn_ipv4 = -1; static int hf_lisp_lcaf_asn_ipv6 = -1; static int hf_lisp_lcaf_asn_mac = -1; static int hf_lisp_lcaf_asn_dn = -1; /* LCAF Geo Coordinates fields */ static int hf_lisp_lcaf_geo_lat = -1; static int hf_lisp_lcaf_geo_lat_hemisphere = -1; static int hf_lisp_lcaf_geo_lat_deg = -1; static int hf_lisp_lcaf_geo_lat_min = -1; static int hf_lisp_lcaf_geo_lat_sec = -1; static int hf_lisp_lcaf_geo_lon = -1; static int hf_lisp_lcaf_geo_lon_hemisphere = -1; static int hf_lisp_lcaf_geo_lon_deg = -1; static int hf_lisp_lcaf_geo_lon_min = -1; static int hf_lisp_lcaf_geo_lon_sec = -1; static int hf_lisp_lcaf_geo_alt = -1; static int hf_lisp_lcaf_geo_afi = -1; static int hf_lisp_lcaf_geo_ipv4 = -1; static int hf_lisp_lcaf_geo_ipv6 = -1; static int hf_lisp_lcaf_geo_mac = -1; static int hf_lisp_lcaf_geo_dn = -1; /* LCAF NATT fields */ static int hf_lisp_lcaf_natt_msport = -1; static int hf_lisp_lcaf_natt_etrport = -1; static int hf_lisp_lcaf_natt_rloc = -1; static int hf_lisp_lcaf_natt_rloc_afi = -1; static int hf_lisp_lcaf_natt_rloc_ipv4 = -1; static int hf_lisp_lcaf_natt_rloc_ipv6 = -1; /* LCAF Nonce Locator fields */ static int hf_lisp_lcaf_nonce_loc_res = -1; static int hf_lisp_lcaf_nonce_loc = -1; static int hf_lisp_lcaf_nonce_loc_afi = -1; static int hf_lisp_lcaf_nonce_loc_ipv4 = -1; static int hf_lisp_lcaf_nonce_loc_ipv6 = -1; static int hf_lisp_lcaf_nonce_loc_mac = -1; static int hf_lisp_lcaf_nonce_loc_dn = -1; /* LCAF Multicast Group Membership Information fields */ static int hf_lisp_lcaf_mcinfo_flags = -1; static int hf_lisp_lcaf_mcinfo_flags_res = -1; static int hf_lisp_lcaf_mcinfo_flags_rp = -1; static int hf_lisp_lcaf_mcinfo_flags_leave = -1; static int hf_lisp_lcaf_mcinfo_flags_join = -1; static int hf_lisp_lcaf_mcinfo_iid = -1; static int hf_lisp_lcaf_mcinfo_res = -1; static int hf_lisp_lcaf_mcinfo_src_masklen = -1; static int hf_lisp_lcaf_mcinfo_grp_masklen = -1; static int hf_lisp_lcaf_mcinfo_src = -1; static int hf_lisp_lcaf_mcinfo_src_afi = -1; static int hf_lisp_lcaf_mcinfo_src_ipv4 = -1; static int hf_lisp_lcaf_mcinfo_src_ipv6 = -1; static int hf_lisp_lcaf_mcinfo_grp = -1; static int hf_lisp_lcaf_mcinfo_grp_afi = -1; static int hf_lisp_lcaf_mcinfo_grp_ipv4 = -1; static int hf_lisp_lcaf_mcinfo_grp_ipv6 = -1; /* LCAF ELP fields */ static int hf_lisp_lcaf_elp_hop = -1; static int hf_lisp_lcaf_elp_hop_flags = -1; static int hf_lisp_lcaf_elp_hop_flags_res = -1; static int hf_lisp_lcaf_elp_hop_flags_lookup = -1; static int hf_lisp_lcaf_elp_hop_flags_probe = -1; static int hf_lisp_lcaf_elp_hop_flags_strict = -1; static int hf_lisp_lcaf_elp_hop_afi = -1; static int hf_lisp_lcaf_elp_hop_ipv4 = -1; static int hf_lisp_lcaf_elp_hop_ipv6 = -1; /* LCAF Source/Destination 2-Tuple Lookups fields */ static int hf_lisp_lcaf_srcdst_res = -1; static int hf_lisp_lcaf_srcdst_src_masklen = -1; static int hf_lisp_lcaf_srcdst_dst_masklen = -1; static int hf_lisp_lcaf_srcdst_src = -1; static int hf_lisp_lcaf_srcdst_src_afi = -1; static int hf_lisp_lcaf_srcdst_src_ipv4 = -1; static int hf_lisp_lcaf_srcdst_src_ipv6 = -1; static int hf_lisp_lcaf_srcdst_src_mac = -1; static int hf_lisp_lcaf_srcdst_dst = -1; static int hf_lisp_lcaf_srcdst_dst_afi = -1; static int hf_lisp_lcaf_srcdst_dst_ipv4 = -1; static int hf_lisp_lcaf_srcdst_dst_ipv6 = -1; static int hf_lisp_lcaf_srcdst_dst_mac = -1; /* LCAF RLE fields */ static int hf_lisp_lcaf_rle_entry = -1; static int hf_lisp_lcaf_rle_entry_res = -1; static int hf_lisp_lcaf_rle_entry_level = -1; static int hf_lisp_lcaf_rle_entry_afi = -1; static int hf_lisp_lcaf_rle_entry_ipv4 = -1; static int hf_lisp_lcaf_rle_entry_ipv6 = -1; /* LCAF Key/Value Pair fields */ static int hf_lisp_lcaf_kv_key = -1; static int hf_lisp_lcaf_kv_key_afi = -1; static int hf_lisp_lcaf_kv_key_ipv4 = -1; static int hf_lisp_lcaf_kv_key_ipv6 = -1; static int hf_lisp_lcaf_kv_key_mac = -1; static int hf_lisp_lcaf_kv_key_dn = -1; static int hf_lisp_lcaf_kv_value = -1; static int hf_lisp_lcaf_kv_value_afi = -1; static int hf_lisp_lcaf_kv_value_ipv4 = -1; static int hf_lisp_lcaf_kv_value_ipv6 = -1; static int hf_lisp_lcaf_kv_value_mac = -1; static int hf_lisp_lcaf_kv_value_dn = -1; /* Vendor Specific LCAF fields */ static int hf_lisp_lcaf_vendor_res = -1; static int hf_lisp_lcaf_vendor_oui = -1; static int hf_lisp_lcaf_vendor_data = -1; /* Encapsulated Control Message fields */ static int hf_lisp_ecm_flags_sec = -1; static int hf_lisp_ecm_flags_ddt = -1; static int hf_lisp_ecm_res = -1; /* Initialize the subtree pointers */ static gint ett_lisp = -1; static gint ett_lisp_mr = -1; static gint ett_lisp_mreq_flags = -1; static gint ett_lisp_mapping = -1; static gint ett_lisp_itr = -1; static gint ett_lisp_record = -1; static gint ett_lisp_lcaf = -1; static gint ett_lisp_lcaf_header = -1; static gint ett_lisp_lcaf_geo_lat = -1; static gint ett_lisp_lcaf_geo_lon = -1; static gint ett_lisp_lcaf_natt_rloc = -1; static gint ett_lisp_lcaf_mcinfo_flags = -1; static gint ett_lisp_lcaf_mcinfo_src = -1; static gint ett_lisp_lcaf_mcinfo_grp = -1; static gint ett_lisp_lcaf_elp_hop = -1; static gint ett_lisp_lcaf_elp_hop_flags = -1; static gint ett_lisp_lcaf_srcdst_src = -1; static gint ett_lisp_lcaf_srcdst_dst = -1; static gint ett_lisp_lcaf_rle_entry = -1; static gint ett_lisp_lcaf_kv_key = -1; static gint ett_lisp_lcaf_kv_value = -1; static gint ett_lisp_lcaf_vendor = -1; static gint ett_lisp_loc = -1; static gint ett_lisp_loc_flags = -1; static gint ett_lisp_info_prefix = -1; static gint ett_lisp_afi_list = -1; static expert_field ei_lisp_undecoded = EI_INIT; static expert_field ei_lisp_expected_field = EI_INIT; static expert_field ei_lisp_invalid_field = EI_INIT; static expert_field ei_lisp_unexpected_field = EI_INIT; static dissector_handle_t lisp_handle; static dissector_handle_t ipv4_handle; static dissector_handle_t ipv6_handle; static gboolean encapsulated = FALSE; static gboolean ddt_originated = FALSE; static const value_string lisp_typevals[] = { { LISP_MAP_REQUEST, "Map-Request" }, { LISP_MAP_REPLY, "Map-Reply" }, { LISP_MAP_REGISTER, "Map-Register" }, { LISP_MAP_NOTIFY, "Map-Notify" }, { LISP_MAP_REFERRAL, "Map-Referral" }, { LISP_INFO, "Info" }, { LISP_ECM, "Encapsulated Control Message" }, { 0, NULL} }; static const value_string mapping_actions[] = { { LISP_ACT_NONE, "No-Action" }, { LISP_ACT_FWD_NATIVE, "Natively-Forward" }, { LISP_ACT_MREQ, "Send-Map-Request" }, { LISP_ACT_DROP, "Drop/No-Reason" }, { LISP_ACT_DROP_PD, "Drop/Policy-Denied" }, { LISP_ACT_DROP_AF, "Drop/Authentication-Failure" }, { LISP_ACT_FWD_UA, "Forward-For-Unknown-Address" }, { 0, NULL} }; static const value_string referral_actions[] = { { DDT_NODE_REF, "Node Referral" }, { DDT_MS_REF, "Map-Server Referral" }, { DDT_MS_ACK, "Map-Server ACK" }, { DDT_MS_NREG, "Map-Server Not Registered" }, { DDT_DLGT_HOLE, "Delegation Hole" }, { DDT_NAUTH, "Not Authoritative" }, { 0, NULL} }; static const value_string lcaf_typevals[] = { { LCAF_NULL, "Null Body" }, { LCAF_AFI_LIST, "AFI List" }, { LCAF_IID, "Instance ID" }, { LCAF_ASN, "AS Number" }, { LCAF_APP_DATA, "Application Data" }, { LCAF_GEO, "Geo Coordinates" }, { LCAF_OKEY, "Opaque Key" }, { LCAF_NATT, "NAT Traversal" }, { LCAF_NONCE_LOC, "Nonce Locator" }, { LCAF_MCAST_INFO, "Multicast Info" }, { LCAF_ELP, "Explicit Locator Path" }, { LCAF_SEC_KEY, "Security Key" }, { LCAF_SRC_DST_KEY, "Source/Dest Key" }, { LCAF_RLE, "Replication List Entry" }, { LCAF_JSON, "JSON Data Model" }, { LCAF_KV_ADDR_PAIR, "Key/Value Address Pair" }, { LCAF_VENDOR, "Vendor Specific LCAF" }, { 0, NULL} }; static const value_string lat_typevals[] = { { 0, "S" }, { 1, "N" }, { 0, NULL} }; static const value_string lon_typevals[] = { { 0, "W" }, { 1, "E" }, { 0, NULL} }; /* Add your company OUI here if you're developing a vendor LCAF dissector */ static const value_string oui_vals[] = { { OUI_CISCO, "Cisco" }, { 0, NULL} }; static int get_lcaf_data(tvbuff_t *tvb, gint offset, guint8 *lcaf_type, guint16 *len) { /* Jump over Rsvd1 and Flags (16 bits) */ offset += 2; /* Type (8 bits) */ if (lcaf_type) *lcaf_type = tvb_get_guint8(tvb, offset); offset += 1; /* Jump over Rsvd2 bits (8 bits) */ offset += 1; /* Length (16 bits) */ if (len) /* Adding the size of the LCAF header as well */ *len = tvb_get_ntohs(tvb, offset) + LCAF_HEADER_LEN; offset += 2; return offset; } const gchar * get_addr_str(wmem_allocator_t *pool, tvbuff_t *tvb, gint offset, guint16 afi, guint16 *addr_len) { const gchar *notset_str = "not set"; const gchar *addr_str; guint8 lcaf_type; guint32 iid, asn; guint16 cur_len; switch (afi) { case AFNUM_RESERVED: *addr_len = 0; return notset_str; case AFNUM_INET: *addr_len = INET_ADDRLEN; addr_str = tvb_ip_to_str(pool, tvb, offset); return addr_str; case AFNUM_INET6: *addr_len = INET6_ADDRLEN; addr_str = tvb_ip6_to_str(pool, tvb, offset); return addr_str; case AFNUM_LCAF: get_lcaf_data(tvb, offset, &lcaf_type, addr_len); addr_str = val_to_str(lcaf_type, lcaf_typevals, "Unknown LCAF Type (%d)"); if (lcaf_type == LCAF_IID) { iid = tvb_get_ntohl(tvb, offset + LCAF_HEADER_LEN); afi = tvb_get_ntohs(tvb, offset + LCAF_HEADER_LEN + 4); addr_str = get_addr_str(pool, tvb, offset + LCAF_HEADER_LEN + 6, afi, &cur_len); return wmem_strdup_printf(pool, "[%d] %s", iid, addr_str); } if (lcaf_type == LCAF_ASN) { asn = tvb_get_ntohl(tvb, offset + LCAF_HEADER_LEN); afi = tvb_get_ntohs(tvb, offset + LCAF_HEADER_LEN + 4); addr_str = get_addr_str(pool, tvb, offset + LCAF_HEADER_LEN + 6, afi, &cur_len); return wmem_strdup_printf(pool, "%s (ASN %d)", addr_str, asn); } return addr_str; case AFNUM_802: case AFNUM_EUI48: *addr_len = EUI48_ADDRLEN; addr_str = tvb_ether_to_str(pool, tvb, offset); return addr_str; case AFNUM_DISTNAME: *addr_len = tvb_strsize(tvb, offset); addr_str = tvb_get_stringz_enc(pool, tvb, offset, NULL, ENC_ASCII); return addr_str; default: return NULL; } } static int dissect_lcaf_natt_rloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, const gchar *str, int idx) { guint16 addr_len = 0; guint16 rloc_afi; const gchar *rloc_str; proto_item *ti; proto_tree *rloc_tree; ti = proto_tree_add_item(tree, hf_lisp_lcaf_natt_rloc, tvb, offset, 2, ENC_NA); rloc_tree = proto_item_add_subtree(ti, ett_lisp_lcaf_natt_rloc); /* AFI (2 bytes) */ proto_tree_add_item(rloc_tree, hf_lisp_lcaf_natt_rloc_afi, tvb, offset, 2, ENC_BIG_ENDIAN); rloc_afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Reencap hop */ rloc_str = get_addr_str(pinfo->pool, tvb, offset, rloc_afi, &addr_len); switch (rloc_afi) { case AFNUM_RESERVED: break; case AFNUM_INET: proto_tree_add_item(rloc_tree, hf_lisp_lcaf_natt_rloc_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); break; case AFNUM_INET6: proto_tree_add_item(rloc_tree, hf_lisp_lcaf_natt_rloc_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); break; case AFNUM_LCAF: dissect_lcaf(tvb, pinfo, rloc_tree, offset, NULL); break; default: expert_add_info_format(pinfo, rloc_tree, &ei_lisp_unexpected_field, "Unexpected NAT-T RLOC AFI (%d), cannot decode", rloc_afi); } if (idx) { proto_item_append_text(ti, str, idx, rloc_str); } else { proto_item_append_text(ti, str, rloc_str); } proto_item_set_len(ti, 2 + addr_len); return addr_len + 2; } static int dissect_lcaf_elp_hop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, int idx, proto_item *tip) { guint16 addr_len = 0; guint16 hop_afi; guint16 hop_flags; const gchar *hop_str; proto_item *ti, *ti_flags; proto_tree *hop_tree, *flags_tree; ti = proto_tree_add_item(tree, hf_lisp_lcaf_elp_hop, tvb, offset, 2, ENC_NA); hop_tree = proto_item_add_subtree(ti, ett_lisp_lcaf_elp_hop); /* Flags (2 bytes) */ ti_flags = proto_tree_add_item(hop_tree, hf_lisp_lcaf_elp_hop_flags, tvb, offset, 2, ENC_BIG_ENDIAN); flags_tree = proto_item_add_subtree(ti_flags, ett_lisp_lcaf_elp_hop_flags); proto_tree_add_item(flags_tree, hf_lisp_lcaf_elp_hop_flags_res, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_lcaf_elp_hop_flags_lookup, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_lcaf_elp_hop_flags_probe, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_lcaf_elp_hop_flags_strict, tvb, offset, 2, ENC_BIG_ENDIAN); hop_flags = tvb_get_ntohs(tvb, offset); offset += 2; /* AFI (2 bytes) */ proto_tree_add_item(hop_tree, hf_lisp_lcaf_elp_hop_afi, tvb, offset, 2, ENC_BIG_ENDIAN); hop_afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Reencap hop */ hop_str = get_addr_str(pinfo->pool, tvb, offset, hop_afi, &addr_len); switch (hop_afi) { case AFNUM_INET: proto_tree_add_item(hop_tree, hf_lisp_lcaf_elp_hop_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); break; case AFNUM_INET6: proto_tree_add_item(hop_tree, hf_lisp_lcaf_elp_hop_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); break; case AFNUM_LCAF: dissect_lcaf(tvb, pinfo, hop_tree, offset, NULL); break; default: expert_add_info_format(pinfo, hop_tree, &ei_lisp_unexpected_field, "Unexpected Reencap Hop AFI (%d), cannot decode", hop_afi); } if (idx) { proto_item_append_text(ti, " %d.", idx); } else { proto_item_append_text(ti, ":"); } proto_item_append_text(ti, " %s", hop_str); proto_item_set_len(ti, 4 + addr_len); if (hop_flags & 0x04) proto_item_append_text(ti, ", Lookup"); if (hop_flags & 0x02) proto_item_append_text(ti, ", RLOC-Probe"); if (hop_flags & 0x01) proto_item_append_text(ti, ", Strict"); proto_item_append_text(tip, ", %s", hop_str); return addr_len + 4; } static int dissect_lcaf_rle_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, int idx, proto_item *tip) { guint8 level; guint16 addr_len = 0; guint16 entry_afi; const gchar *entry_str; proto_item *ti; proto_tree *entry_tree; ti = proto_tree_add_item(tree, hf_lisp_lcaf_rle_entry, tvb, offset, 2, ENC_NA); entry_tree = proto_item_add_subtree(ti, ett_lisp_lcaf_rle_entry); /* Reserved (3 bytes) */ proto_tree_add_item(entry_tree, hf_lisp_lcaf_rle_entry_res, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; /* Level Value (1 byte) */ proto_tree_add_item(entry_tree, hf_lisp_lcaf_rle_entry_level, tvb, offset, 1, ENC_BIG_ENDIAN); level = tvb_get_guint8(tvb, offset); offset += 1; /* AFI (2 bytes) */ proto_tree_add_item(entry_tree, hf_lisp_lcaf_rle_entry_afi, tvb, offset, 2, ENC_BIG_ENDIAN); entry_afi = tvb_get_ntohs(tvb, offset); offset += 2; /* RTR/ETR entry */ entry_str = get_addr_str(pinfo->pool, tvb, offset, entry_afi, &addr_len); switch (entry_afi) { case AFNUM_INET: proto_tree_add_item(entry_tree, hf_lisp_lcaf_rle_entry_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); break; case AFNUM_INET6: proto_tree_add_item(entry_tree, hf_lisp_lcaf_rle_entry_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); break; case AFNUM_LCAF: dissect_lcaf(tvb, pinfo, entry_tree, offset, NULL); break; default: expert_add_info_format(pinfo, entry_tree, &ei_lisp_unexpected_field, "Unexpected RTR/ETR AFI (%d), cannot decode", entry_afi); } if (idx) { proto_item_append_text(ti, " %d.", idx); } else { proto_item_append_text(ti, ":"); } proto_item_append_text(ti, " %s, level %d", entry_str, level); proto_item_set_len(ti, 6 + addr_len); proto_item_append_text(tip, ", %s (%d)", entry_str, level); return addr_len + 6; } /* * Dissector code for AFI List * */ static int dissect_lcaf_afi_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint16 length) { gint old_offset; gint remaining = length; gint i = 1; gint str_len; guint16 addr_len = 0; guint16 afi; const gchar *lcaf_str; gchar *disp_str; proto_item *tir; proto_tree *lisp_afi_list_tree; while (remaining > 0) { afi = tvb_get_ntohs(tvb, offset); tir = proto_tree_add_item(tree, hf_lisp_lcaf_afi_list_item, tvb, offset, LCAF_HEADER_LEN, ENC_NA); lisp_afi_list_tree = proto_item_add_subtree(tir, ett_lisp_afi_list); proto_tree_add_item(lisp_afi_list_tree, hf_lisp_lcaf_afi_list_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; remaining -= 2; switch (afi) { case AFNUM_INET: proto_tree_add_item(lisp_afi_list_tree, hf_lisp_lcaf_afi_list_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); proto_item_append_text(tir, " %d. IPv4 Address: %s", i, tvb_ip_to_str(pinfo->pool, tvb, offset)); proto_item_set_len(tir, 2 + INET_ADDRLEN); offset += INET_ADDRLEN; remaining -= INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(lisp_afi_list_tree, hf_lisp_lcaf_afi_list_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); proto_item_append_text(tir, " %d. IPv6 Address: %s", i, tvb_ip6_to_str(pinfo->pool, tvb, offset)); proto_item_set_len(tir, 2 + INET6_ADDRLEN); offset += INET6_ADDRLEN; remaining -= INET6_ADDRLEN; break; case AFNUM_LCAF: old_offset = offset; lcaf_str = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); proto_item_append_text(tir, " %d. %s", i, lcaf_str); proto_item_set_len(tir, 2 + addr_len); offset = dissect_lcaf(tvb, pinfo, lisp_afi_list_tree, offset, tir); remaining -= (offset - old_offset); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(lisp_afi_list_tree, hf_lisp_lcaf_afi_list_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); proto_item_append_text(tir, " %d. MAC Address: %s", i, tvb_ether_to_str(pinfo->pool, tvb, offset)); proto_item_set_len(tir, 2 + EUI48_ADDRLEN); offset += EUI48_ADDRLEN; remaining -= EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item_ret_display_string(lisp_afi_list_tree, hf_lisp_lcaf_afi_list_dn, tvb, offset, str_len, ENC_ASCII, pinfo->pool, &disp_str); proto_item_append_text(tir, " %d. Distinguished Name: %s", i, disp_str); offset += str_len; remaining -= str_len; break; default: expert_add_info_format(pinfo, tree, &ei_lisp_unexpected_field, "Unexpected AFI (%d), cannot decode", afi); return -1; } i++; } return offset; } /* * Dissector code for Instance ID * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 2 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Instance ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_iid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, proto_item *tip) { const gchar *ip_address; guint16 afi, addr_len = 0; gint str_len; /* Instance ID (4 bytes) */ proto_tree_add_item(tree, hf_lisp_lcaf_iid, tvb, offset, 4, ENC_BIG_ENDIAN); proto_item_append_text(tip, ": %d", tvb_get_ntohl(tvb, offset)); offset += 4; /* AFI (2 bytes) */ afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_iid_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Address */ ip_address = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); if (ip_address && afi) proto_item_append_text(tip, ", Address: %s", ip_address); switch (afi) { case AFNUM_RESERVED: break; case AFNUM_INET: proto_tree_add_item(tree, hf_lisp_lcaf_iid_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(tree, hf_lisp_lcaf_iid_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(tree, hf_lisp_lcaf_iid_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_iid_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; default: expert_add_info_format(pinfo, tree, &ei_lisp_unexpected_field, "Unexpected Instance ID AFI (%d), cannot decode", afi); } return offset; } /* * Dissector code for AS Number * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 3 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AS Number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_asn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, proto_item *tip) { const gchar *addr; guint16 afi, addr_len = 0; gint str_len; /* AS Number (4 bytes) */ proto_tree_add_item(tree, hf_lisp_lcaf_asn, tvb, offset, 4, ENC_BIG_ENDIAN); proto_item_append_text(tip, ": %d", tvb_get_ntohl(tvb, offset)); offset += 4; /* AFI (2 bytes) */ afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_asn_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Address */ addr = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); if (addr && afi) proto_item_append_text(tip, ", Address: %s", addr); switch (afi) { case AFNUM_RESERVED: break; case AFNUM_INET: proto_tree_add_item(tree, hf_lisp_lcaf_asn_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(tree, hf_lisp_lcaf_asn_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(tree, hf_lisp_lcaf_asn_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_asn_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; default: expert_add_info_format(pinfo, tree, &ei_lisp_unexpected_field, "Unexpected Instance ID AFI (%d), cannot decode", afi); } return offset; } /* * Dissector code for Geo Coordinates LCAF * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 5 | Rsvd2 | 12 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |N| Latitude Degrees | Minutes | Seconds | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |E| Longitude Degrees | Minutes | Seconds | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Altitude | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_geo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, proto_item *tir) { guint16 addr_len = 0; gboolean north, east; guint16 deg; guint8 min, sec; guint32 alt; guint16 afi; gint str_len; const gchar *ip_address; const guint16 mask = 0x7FFF; /* prepare mask for N or E bit */ proto_item *ti_lat, *ti_lon, *ti_alt; proto_tree *lat_tree, *lon_tree; /* PROCESS LATITUDE */ ti_lat = proto_tree_add_item(tree, hf_lisp_lcaf_geo_lat, tvb, offset, 4, ENC_NA); lat_tree = proto_item_add_subtree(ti_lat, ett_lisp_lcaf_geo_lat); /* Hemisphere and degrees (2 bytes) */ proto_tree_add_item(lat_tree, hf_lisp_lcaf_geo_lat_hemisphere, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(lat_tree, hf_lisp_lcaf_geo_lat_deg, tvb, offset, 2, ENC_BIG_ENDIAN); deg = tvb_get_ntohs(tvb, offset); north = deg >> 15; deg &= mask; if (deg > 90) expert_add_info_format(pinfo, tree, &ei_lisp_invalid_field, "Invalid latitude degrees value (%d)", deg); offset += 2; /* Minutes (1 byte) */ proto_tree_add_item(lat_tree, hf_lisp_lcaf_geo_lat_min, tvb, offset, 1, ENC_BIG_ENDIAN); min = tvb_get_guint8(tvb, offset); if (min > 60) expert_add_info_format(pinfo, tree, &ei_lisp_invalid_field, "Invalid latitude minutes value (%d)", min); offset += 1; /* Seconds (1 byte) */ proto_tree_add_item(lat_tree, hf_lisp_lcaf_geo_lat_sec, tvb, offset, 1, ENC_BIG_ENDIAN); sec = tvb_get_guint8(tvb, offset); if (sec > 60) expert_add_info_format(pinfo, tree, &ei_lisp_invalid_field, "Invalid latitude seconds value (%d)", min); offset += 1; proto_item_append_text(ti_lat, ": %s %d" UTF8_DEGREE_SIGN "%d' %d\"", val_to_str_const(north, lat_typevals, ""), deg, min, sec); proto_item_append_text(tir, ": (%s%d" UTF8_DEGREE_SIGN "%d'%d\"", val_to_str_const(north, lat_typevals, ""), deg, min, sec); /* PROCESS LONGITUDE */ ti_lon = proto_tree_add_item(tree, hf_lisp_lcaf_geo_lon, tvb, offset, 4, ENC_NA); lon_tree = proto_item_add_subtree(ti_lon, ett_lisp_lcaf_geo_lon); /* Hemisphere and degrees (2 bytes) */ proto_tree_add_item(lon_tree, hf_lisp_lcaf_geo_lon_hemisphere, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(lon_tree, hf_lisp_lcaf_geo_lon_deg, tvb, offset, 2, ENC_BIG_ENDIAN); deg = tvb_get_ntohs(tvb, offset); east = deg >> 15; deg &= mask; if (deg > 180) expert_add_info_format(pinfo, tree, &ei_lisp_invalid_field, "Invalid longitude degrees value (%d)", deg); offset += 2; /* Minutes (1 byte) */ proto_tree_add_item(lon_tree, hf_lisp_lcaf_geo_lon_min, tvb, offset, 1, ENC_BIG_ENDIAN); min = tvb_get_guint8(tvb, offset); if (min > 60) expert_add_info_format(pinfo, tree, &ei_lisp_invalid_field, "Invalid longitude minutes value (%d)", min); offset += 1; /* Seconds (1 byte) */ proto_tree_add_item(lon_tree, hf_lisp_lcaf_geo_lon_sec, tvb, offset, 1, ENC_BIG_ENDIAN); sec = tvb_get_guint8(tvb, offset); if (sec > 60) expert_add_info_format(pinfo, tree, &ei_lisp_invalid_field, "Invalid longitude seconds value (%d)", min); offset += 1; proto_item_append_text(ti_lon, ": %s %d" UTF8_DEGREE_SIGN " %d' %d\"", val_to_str_const(east, lon_typevals, ""), deg, min, sec); proto_item_append_text(tir, ", %s%d" UTF8_DEGREE_SIGN "%d'%d\")", val_to_str_const(east, lon_typevals, ""), deg, min, sec); /* PROCESS ALTITUDE */ ti_alt = proto_tree_add_item(tree, hf_lisp_lcaf_geo_alt, tvb, offset, 4, ENC_NA); alt = tvb_get_ntohl(tvb, offset); /* if altitude equals 0x7fffffff then no altitude information encoded */ if (alt == 0x7fffffff) { proto_item_append_text(ti_alt, ": no value encoded"); } else { proto_item_append_text(ti_alt, ": %d m", alt); proto_item_append_text(tir, ", Altitude: %d m", alt); } offset += 4; /* PROCESS ADDRESS */ /* AFI (2 bytes) */ afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_geo_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ip_address = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); if (ip_address && afi) proto_item_append_text(tir, ", Address: %s", ip_address); switch (afi) { case AFNUM_RESERVED: break; case AFNUM_INET: proto_tree_add_item(tree, hf_lisp_lcaf_geo_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(tree, hf_lisp_lcaf_geo_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(tree, hf_lisp_lcaf_geo_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_geo_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; default: expert_add_info_format(pinfo, tree, &ei_lisp_unexpected_field, "Unexpected Geo Coordinates AFI (%d), cannot decode", afi); } return offset; } /* * Dissector code for NAT-Traversal * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 7 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MS UDP Port Number | ETR UDP Port Number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Global ETR RLOC Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | MS RLOC Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Private ETR RLOC Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR RLOC Address 1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR RLOC Address n ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_natt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint16 length) { gint i; gint len; gint remaining = length; const gchar *global_etr = " of Global ETR: %s"; const gchar *ms = " of MS: %s"; const gchar *private_etr = " of Private ETR: %s"; const gchar *rtr = " of RTR %d: %s"; remaining -= 4; proto_tree_add_item(tree, hf_lisp_lcaf_natt_msport, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; remaining -= 2; proto_tree_add_item(tree, hf_lisp_lcaf_natt_etrport, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; remaining -= 2; len = dissect_lcaf_natt_rloc(tvb, pinfo, tree, offset, global_etr, 0); offset += len; remaining -= len; len = dissect_lcaf_natt_rloc(tvb, pinfo, tree, offset, ms, 0); offset += len; remaining -= len; len = dissect_lcaf_natt_rloc(tvb, pinfo, tree, offset, private_etr, 0); offset += len; remaining -= len; i = 1; while (remaining > 0) { len = dissect_lcaf_natt_rloc(tvb, pinfo, tree, offset, rtr, i); offset += len; remaining -= len; i++; } return offset; } /* * Dissector code for Nonce Locator * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 8 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved | Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_nonce_loc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, proto_item *tip) { const gchar *addr; guint16 afi, addr_len = 0; gint str_len; /* Reserved (1 byte) */ proto_tree_add_item(tree, hf_lisp_lcaf_nonce_loc_res, tvb, offset, 1, ENC_BIG_ENDIAN); proto_item_append_text(tip, ": %d", tvb_get_ntohl(tvb, offset)); offset += 1; /* Nonce (3 bytes) */ proto_tree_add_item(tree, hf_lisp_lcaf_nonce_loc, tvb, offset, 3, ENC_BIG_ENDIAN); proto_item_append_text(tip, ": %d", tvb_get_ntohl(tvb, offset)); offset += 3; /* AFI (2 bytes) */ afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_nonce_loc_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Address */ addr = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); if (addr && afi) proto_item_append_text(tip, ", Address: %s", addr); switch (afi) { case AFNUM_RESERVED: break; case AFNUM_INET: proto_tree_add_item(tree, hf_lisp_lcaf_nonce_loc_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(tree, hf_lisp_lcaf_nonce_loc_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(tree, hf_lisp_lcaf_nonce_loc_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(tree, hf_lisp_lcaf_nonce_loc_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; default: expert_add_info_format(pinfo, tree, &ei_lisp_unexpected_field, "Unexpected Instance ID AFI (%d), cannot decode", afi); } return offset; } /* * Dissector code for Multicast Group Membership Information * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 9 | Rsvd2 |R|L|J| 8 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Instance-ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved | Source MaskLen| Group MaskLen | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Source/Subnet Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Group Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_mcast_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, proto_item *tir) { guint8 src_masklen, grp_masklen; guint16 afi, addr_len = 0; guint32 iid; const gchar *src_str, *grp_str; proto_item *ti_src, *ti_grp; proto_tree *src_tree, *grp_tree; /* Instance ID (4 bytes) */ proto_tree_add_item(tree, hf_lisp_lcaf_mcinfo_iid, tvb, offset, 4, ENC_BIG_ENDIAN); iid = tvb_get_ntohl(tvb, offset); offset += 4; /* Reserved (2 bytes) */ proto_tree_add_item(tree, hf_lisp_lcaf_mcinfo_res, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Source Mask Length (1 byte) */ proto_tree_add_item(tree, hf_lisp_lcaf_mcinfo_src_masklen, tvb, offset, 1, ENC_BIG_ENDIAN); src_masklen = tvb_get_guint8(tvb, offset); offset += 1; /* Group Mask Length (1 byte) */ proto_tree_add_item(tree, hf_lisp_lcaf_mcinfo_grp_masklen, tvb, offset, 1, ENC_BIG_ENDIAN); grp_masklen = tvb_get_guint8(tvb, offset); offset += 1; ti_src = proto_tree_add_item(tree, hf_lisp_lcaf_mcinfo_src, tvb, offset, 2, ENC_NA); src_tree = proto_item_add_subtree(ti_src, ett_lisp_lcaf_mcinfo_src); /* Source/Subnet AFI (2 bytes) */ proto_tree_add_item(src_tree, hf_lisp_lcaf_mcinfo_src_afi, tvb, offset, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Source/Subnet Address */ src_str = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); switch (afi) { case AFNUM_INET: proto_tree_add_item(src_tree, hf_lisp_lcaf_mcinfo_src_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(src_tree, hf_lisp_lcaf_mcinfo_src_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, src_tree, offset, NULL); break; default: expert_add_info_format(pinfo, src_tree, &ei_lisp_unexpected_field, "Unexpected Source Prefix AFI (%d), cannot decode", afi); } proto_item_append_text(ti_src, ": %s", src_str); proto_item_set_len(ti_src, 2 + addr_len); ti_grp = proto_tree_add_item(tree, hf_lisp_lcaf_mcinfo_grp, tvb, offset, 2, ENC_NA); grp_tree = proto_item_add_subtree(ti_grp, ett_lisp_lcaf_mcinfo_grp); /* Group AFI (2 bytes) */ proto_tree_add_item(grp_tree, hf_lisp_lcaf_mcinfo_grp_afi, tvb, offset, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Group Address */ grp_str = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); switch (afi) { case AFNUM_INET: proto_tree_add_item(grp_tree, hf_lisp_lcaf_mcinfo_grp_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(grp_tree, hf_lisp_lcaf_mcinfo_grp_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, grp_tree, offset, NULL); break; default: expert_add_info_format(pinfo, grp_tree, &ei_lisp_unexpected_field, "Unexpected Destination Prefix AFI (%d), cannot decode", afi); } proto_item_append_text(ti_grp, ": %s", grp_str); proto_item_set_len(ti_grp, 2 + addr_len); proto_item_append_text(tir, " ([%d], %s/%d, %s/%d)", iid, src_str, src_masklen, grp_str, grp_masklen); return offset; } /* * Dissector code for Explicit Locator Path * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 10 | Rsvd2 | n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 |L|P|S| AFI = x | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reencap Hop 1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 |L|P|S| AFI = x | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reencap Hop k ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * */ static int dissect_lcaf_elp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint16 length, proto_item *tir) { gint len; gint remaining = length; gint i = 1; while (remaining > 0) { len = dissect_lcaf_elp_hop(tvb, pinfo, tree, offset, i, tir); offset += len; remaining -= len; i++; } return offset; } /* * Dissector code for Source/Destination 2-Tuple Lookups * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 12 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved | Source-ML | Dest-ML | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Source-Prefix ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Destination-Prefix ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_src_dst_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, proto_item *tir) { guint8 src_masklen, dst_masklen; guint16 afi, addr_len = 0; const gchar *src_str, *dst_str; proto_item *ti_src, *ti_dst; proto_tree *src_tree, *dst_tree; /* Reserved (2 bytes) */ proto_tree_add_item(tree, hf_lisp_lcaf_srcdst_res, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Source Prefix Mask Length (1 byte) */ proto_tree_add_item(tree, hf_lisp_lcaf_srcdst_src_masklen, tvb, offset, 1, ENC_BIG_ENDIAN); src_masklen = tvb_get_guint8(tvb, offset); offset += 1; /* Destination Prefix Mask Length (1 byte) */ proto_tree_add_item(tree, hf_lisp_lcaf_srcdst_dst_masklen, tvb, offset, 1, ENC_BIG_ENDIAN); dst_masklen = tvb_get_guint8(tvb, offset); offset += 1; ti_src = proto_tree_add_item(tree, hf_lisp_lcaf_srcdst_src, tvb, offset, 2, ENC_NA); src_tree = proto_item_add_subtree(ti_src, ett_lisp_lcaf_srcdst_src); /* Source Prefix AFI (2 bytes) */ proto_tree_add_item(src_tree, hf_lisp_lcaf_srcdst_src_afi, tvb, offset, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Source Prefix */ src_str = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); switch (afi) { case AFNUM_INET: proto_tree_add_item(src_tree, hf_lisp_lcaf_srcdst_src_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(src_tree, hf_lisp_lcaf_srcdst_src_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, src_tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(src_tree, hf_lisp_lcaf_srcdst_src_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; default: expert_add_info_format(pinfo, src_tree, &ei_lisp_unexpected_field, "Unexpected Source Prefix AFI (%d), cannot decode", afi); } proto_item_append_text(ti_src, ": %s", src_str); proto_item_set_len(ti_src, 2 + addr_len); ti_dst = proto_tree_add_item(tree, hf_lisp_lcaf_srcdst_dst, tvb, offset, 2, ENC_NA); dst_tree = proto_item_add_subtree(ti_dst, ett_lisp_lcaf_srcdst_dst); /* Destination Prefix AFI (2 bytes) */ proto_tree_add_item(dst_tree, hf_lisp_lcaf_srcdst_dst_afi, tvb, offset, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Destination Prefix */ dst_str = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); switch (afi) { case AFNUM_INET: proto_tree_add_item(dst_tree, hf_lisp_lcaf_srcdst_dst_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(dst_tree, hf_lisp_lcaf_srcdst_dst_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, dst_tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(dst_tree, hf_lisp_lcaf_srcdst_dst_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; default: expert_add_info_format(pinfo, dst_tree, &ei_lisp_unexpected_field, "Unexpected Destination Prefix AFI (%d), cannot decode", afi); } proto_item_append_text(ti_dst, ": %s", dst_str); proto_item_set_len(ti_dst, 2 + addr_len); proto_item_append_text(tir, " (%s/%d, %s/%d)", src_str, src_masklen, dst_str, dst_masklen); return offset; } /* * Dissector code for Replication List Entries for Multicast Forwarding * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 13 | Rsvd2 | 4 + n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 | Rsvd4 | Level Value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR/ETR #1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 | Rsvd4 | Level Value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | RTR/ETR #n ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_rle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint16 length, proto_item *tir) { gint len; gint remaining = length; gint i = 1; while (remaining > 0) { len = dissect_lcaf_rle_entry(tvb, pinfo, tree, offset, i, tir); offset += len; remaining -= len; i++; } return offset; } /* * Dissector code for Key/Value Address Pairs * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 15 | Rsvd2 | n | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address as Key ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = x | Address as Value ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_kv_addr_pair(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset) { guint16 afi, addr_len = 0; const gchar *key_str, *value_str; proto_item *ti_key, *ti_value; proto_tree *key_tree, *value_tree; gint str_len; ti_key = proto_tree_add_item(tree, hf_lisp_lcaf_kv_key, tvb, offset, 2, ENC_NA); key_tree = proto_item_add_subtree(ti_key, ett_lisp_lcaf_kv_key); /* Key AFI (2 bytes) */ proto_tree_add_item(key_tree, hf_lisp_lcaf_kv_key_afi, tvb, offset, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Key */ key_str = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); switch (afi) { case AFNUM_INET: proto_tree_add_item(key_tree, hf_lisp_lcaf_kv_key_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(key_tree, hf_lisp_lcaf_kv_key_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, key_tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(key_tree, hf_lisp_lcaf_kv_key_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(key_tree, hf_lisp_lcaf_kv_key_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; default: expert_add_info_format(pinfo, key_tree, &ei_lisp_unexpected_field, "Unexpected Key AFI (%d), cannot decode", afi); } proto_item_append_text(ti_key, ": %s", key_str); proto_item_set_len(ti_key, 2 + addr_len); ti_value = proto_tree_add_item(tree, hf_lisp_lcaf_kv_value, tvb, offset, 2, ENC_NA); value_tree = proto_item_add_subtree(ti_value, ett_lisp_lcaf_kv_value); /* Value AFI (2 bytes) */ proto_tree_add_item(value_tree, hf_lisp_lcaf_kv_value_afi, tvb, offset, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, offset); offset += 2; /* Value */ value_str = get_addr_str(pinfo->pool, tvb, offset, afi, &addr_len); switch (afi) { case AFNUM_INET: proto_tree_add_item(value_tree, hf_lisp_lcaf_kv_value_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(value_tree, hf_lisp_lcaf_kv_value_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: offset = dissect_lcaf(tvb, pinfo, value_tree, offset, NULL); break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(value_tree, hf_lisp_lcaf_kv_value_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(value_tree, hf_lisp_lcaf_kv_value_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; default: expert_add_info_format(pinfo, value_tree, &ei_lisp_unexpected_field, "Unexpected Value AFI (%d), cannot decode", afi); } proto_item_append_text(ti_value, ": %s", value_str); proto_item_set_len(ti_value, 2 + addr_len); return offset; } /* * Dissector code for Vendor Specific LCAF * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 255 | Rsvd2 | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd3 | Organizationally Unique Identifier (OUI) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Internal format... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lcaf_vendor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint16 length) { gint len; proto_item *ti_vendor; proto_tree *vendor_tree; /* Reserved (1 byte) */ proto_tree_add_item(tree, hf_lisp_lcaf_vendor_res, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Organizationally Unique Identifier (3 bytes) */ proto_tree_add_item(tree, hf_lisp_lcaf_vendor_oui, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; /* Vendor Data */ len = length - 4; ti_vendor = proto_tree_add_item(tree, hf_lisp_lcaf_vendor_data, tvb, offset, len, ENC_NA); vendor_tree = proto_item_add_subtree(ti_vendor, ett_lisp_lcaf_vendor); expert_add_info_format(pinfo, vendor_tree, &ei_lisp_undecoded, "Look up the vendor's OUI (IEEE 802-2001) and contact them for support on decoding this field"); offset += len; return offset; } /* * Dissector code for LISP Canonical Address Format (LCAF) * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI = 16387 | Rsvd1 | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Rsvd2 | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Type 0: Null Body Type * Type 1: AFI List Type * Type 2: Instance ID Type * Type 3: AS Number Type * Type 4: Application Data Type * Type 5: Geo Coordinates Type * Type 6: Opaque Key Type * Type 7: NAT-Traversal Type * Type 8: Nonce Locator Type * Type 9: Multicast Info Type * Type 10: Explicit Locator Path Type * Type 11: Security Key Type * Type 12: Source/Dest Key Type * Type 13: Replication List Entry Type * Type 14: JSON Data Model Type * Type 15: Key/Value Address Pair Type * Type 255: Vendor Specific LCAF * */ int dissect_lcaf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, proto_item *tip) { guint8 lcaf_type; guint16 len; proto_item *tir, *ti_header, *ti_flags, *ti; proto_tree *lcaf_tree, *lcaf_header_tree, *flags_tree; len = tvb_get_ntohs(tvb, offset + 4); tir = proto_tree_add_item(tree, hf_lisp_lcaf, tvb, offset, LCAF_HEADER_LEN + len, ENC_NA); lcaf_tree = proto_item_add_subtree(tir, ett_lisp_lcaf); ti_header = proto_tree_add_item(lcaf_tree, hf_lisp_lcaf_header, tvb, offset, LCAF_HEADER_LEN, ENC_NA); lcaf_header_tree = proto_item_add_subtree(ti_header, ett_lisp_lcaf_header); /* Reserved bits (8 bits) */ proto_tree_add_item(lcaf_header_tree, hf_lisp_lcaf_res1, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Flags (8 bits) */ proto_tree_add_item(lcaf_header_tree, hf_lisp_lcaf_flags, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Type (8 bits) */ proto_tree_add_item(lcaf_header_tree, hf_lisp_lcaf_type, tvb, offset, 1, ENC_BIG_ENDIAN); lcaf_type = tvb_get_guint8(tvb, offset); proto_item_append_text(tir, ": %s", val_to_str(lcaf_type, lcaf_typevals, "Unknown (%d)")); offset += 1; if (lcaf_type == LCAF_MCAST_INFO) { ti_flags = proto_tree_add_item(lcaf_header_tree, hf_lisp_lcaf_mcinfo_flags, tvb, offset, 1, ENC_BIG_ENDIAN); flags_tree = proto_item_add_subtree(ti_flags, ett_lisp_lcaf_mcinfo_flags); /* Reserved (5 bits) */ proto_tree_add_item(flags_tree, hf_lisp_lcaf_mcinfo_flags_res, tvb, offset, 1, ENC_BIG_ENDIAN); /* Flags (3 bits) */ proto_tree_add_item(flags_tree, hf_lisp_lcaf_mcinfo_flags_rp, tvb, offset, 1, ENC_NA); proto_tree_add_item(flags_tree, hf_lisp_lcaf_mcinfo_flags_leave, tvb, offset, 1, ENC_NA); proto_tree_add_item(flags_tree, hf_lisp_lcaf_mcinfo_flags_join, tvb, offset, 1, ENC_NA); } else { /* Reserved (8 bits) */ proto_tree_add_item(lcaf_header_tree, hf_lisp_lcaf_res2, tvb, offset, 1, ENC_BIG_ENDIAN); } offset += 1; /* Length (16 bits) */ proto_tree_add_item(lcaf_header_tree, hf_lisp_lcaf_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ti = (tip) ? tip : tir; switch (lcaf_type) { case LCAF_NULL: break; case LCAF_AFI_LIST: offset = dissect_lcaf_afi_list(tvb, pinfo, lcaf_tree, offset, len); break; case LCAF_IID: offset = dissect_lcaf_iid(tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_ASN: offset = dissect_lcaf_asn(tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_GEO: offset = dissect_lcaf_geo(tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_NATT: offset = dissect_lcaf_natt(tvb, pinfo, lcaf_tree, offset, len); break; case LCAF_NONCE_LOC: offset = dissect_lcaf_nonce_loc(tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_MCAST_INFO: offset = dissect_lcaf_mcast_info(tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_ELP: offset = dissect_lcaf_elp(tvb, pinfo, lcaf_tree, offset, len, ti); break; case LCAF_SRC_DST_KEY: offset = dissect_lcaf_src_dst_key(tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_RLE: offset = dissect_lcaf_rle(tvb, pinfo, lcaf_tree, offset, len, ti); break; case LCAF_KV_ADDR_PAIR: offset = dissect_lcaf_kv_addr_pair(tvb, pinfo, lcaf_tree, offset); break; case LCAF_VENDOR: offset = dissect_lcaf_vendor(tvb, pinfo, lcaf_tree, offset, len); break; default: proto_tree_add_expert(tree, pinfo, &ei_lisp_undecoded, tvb, offset, len); return offset + len; } return offset; } /* * Dissector code for locator records within control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Priority | Weight | M Priority | M Weight | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Unused Flags |L|p|R| Loc-AFI | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Locator | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lisp_locator(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_mapping_tree, int rec) { gint offset = 0; guint16 addr_len = 0; guint8 prio; guint8 weight; guint8 m_prio; guint8 m_weight; guint16 flags; guint16 loc_afi; const gchar *locator; proto_item *tir, *ti_flags; proto_tree *lisp_lcaf_tree, *lisp_loc_tree, *lisp_flags_tree; tir = proto_tree_add_item(lisp_mapping_tree, hf_lisp_loc, tvb, offset, 8, ENC_NA); lisp_loc_tree = proto_item_add_subtree(tir, ett_lisp_loc); proto_tree_add_item(lisp_loc_tree, hf_lisp_loc_priority, tvb, offset, 1, ENC_BIG_ENDIAN); prio = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(lisp_loc_tree, hf_lisp_loc_weight, tvb, offset, 1, ENC_BIG_ENDIAN); weight = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(lisp_loc_tree, hf_lisp_loc_mpriority, tvb, offset, 1, ENC_BIG_ENDIAN); m_prio = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(lisp_loc_tree, hf_lisp_loc_mweight, tvb, offset, 1, ENC_BIG_ENDIAN); m_weight = tvb_get_guint8(tvb, offset); offset += 1; ti_flags = proto_tree_add_item(lisp_loc_tree, hf_lisp_loc_flags, tvb, offset, 2, ENC_BIG_ENDIAN); lisp_flags_tree = proto_item_add_subtree(ti_flags, ett_lisp_loc_flags); proto_tree_add_item(lisp_flags_tree, hf_lisp_loc_flags_res, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_flags_tree, hf_lisp_loc_flags_local, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_flags_tree, hf_lisp_loc_flags_probe, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_flags_tree, hf_lisp_loc_flags_reach, tvb, offset, 2, ENC_BIG_ENDIAN); flags = tvb_get_ntohs(tvb, offset); offset += 2; proto_tree_add_item(lisp_loc_tree, hf_lisp_loc_afi, tvb, offset, 2, ENC_BIG_ENDIAN); loc_afi = tvb_get_ntohs(tvb, offset); offset += 2; locator = get_addr_str(pinfo->pool, tvb, offset, loc_afi, &addr_len); if (locator == NULL) { expert_add_info_format(pinfo, lisp_mapping_tree, &ei_lisp_unexpected_field, "Unexpected locator AFI (%d), cannot decode", loc_afi); return offset; } if (loc_afi == AFNUM_LCAF) { /* Create a sub-tree for the mapping */ lisp_lcaf_tree = proto_item_add_subtree(tir, ett_lisp_lcaf); offset = dissect_lcaf(tvb, pinfo, lisp_lcaf_tree, offset, NULL); } else { proto_tree_add_string(lisp_loc_tree, hf_lisp_loc_locator, tvb, offset, addr_len, locator); offset += addr_len; } proto_item_append_text(tir, " %d, %sRLOC: %s%s, %s, Priority/Weight: %d/%d, Multicast Priority/Weight: %d/%d", rec, (flags&LOCAL_BIT_MASK) ? "Local " : "", locator, (flags&PROBE_BIT_MASK) ? " (probed)" : "", (flags&REACH_BIT_MASK) ? "Reachable" : "Unreachable", prio, weight, m_prio, m_weight); proto_item_set_len(tir, 8 + addr_len); return offset; } /* * Dissector code for mapping records within control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Record TTL | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Locator Count | EID mask-len | ACT |A| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Rsvd | Map-Version Number | EID-AFI | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | EID-prefix | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ int dissect_lisp_mapping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree, guint8 rec_cnt, int rec, gboolean referral, gint offset, proto_item *tim) { int i; gint str_len; guint16 addr_len = 0; guint8 prefix_mask, loc_cnt; guint16 flags; guint16 act; guint16 prefix_afi, eid_afi; const gchar *prefix; proto_item *tir; proto_tree *lisp_mapping_tree, *lcaf_prefix_tree; prefix_mask = tvb_get_guint8(tvb, offset + 5); flags = tvb_get_ntohs(tvb, offset + 6); prefix_afi = tvb_get_ntohs(tvb, offset + 10); act = flags & LISP_MAP_ACT; act >>= 13; prefix = get_addr_str(pinfo->pool, tvb, offset + 12, prefix_afi, &addr_len); if (prefix == NULL) { expert_add_info_format(pinfo, lisp_tree, &ei_lisp_unexpected_field, "Unexpected EID prefix AFI (%d), cannot decode", prefix_afi); return offset; } tir = proto_tree_add_item(lisp_tree, hf_lisp_mapping, tvb, offset, 12 + addr_len, ENC_NA); if (tim) { proto_item_append_text(tim, " for %s/%d", prefix, prefix_mask); } /* Update the INFO column if there is only one record */ if (rec_cnt == 1) col_append_fstr(pinfo->cinfo, COL_INFO, " for %s/%d", prefix, prefix_mask); /* Create a sub-tree for the mapping */ lisp_mapping_tree = proto_item_add_subtree(tir, ett_lisp_mapping); proto_item_append_text(tir, " %d, EID Prefix: %s/%d", rec, prefix, prefix_mask); /* TTL (32 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_ttl, tvb, offset, 4, ENC_BIG_ENDIAN); if (tvb_get_ntohl(tvb, offset) == 0xFFFFFFFF) { proto_item_append_text(tir, ", TTL: Unlimited"); } else { proto_item_append_text(tir, ", TTL: %d", tvb_get_ntohl(tvb, offset)); } offset += 4; /* Locator count (8 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_loccnt, tvb, offset, 1, ENC_BIG_ENDIAN); loc_cnt = tvb_get_guint8(tvb, offset); offset += 1; /* EID mask length (8 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_eid_masklen, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Action (3 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_act, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(tir, ", %s%s%s", (referral) ? "" : "Action: ", val_to_str(act, (referral) ? referral_actions : mapping_actions, "Invalid action code (%d)"), (referral&&(flags&REFERRAL_INCOMPLETE)) ? " (Incomplete)" : ""); /* Authoritative bit */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_auth, tvb, offset, 2, ENC_BIG_ENDIAN); if (flags&LISP_MAP_AUTH) { proto_item_append_text(tir, ", Authoritative"); } else { proto_item_append_text(tir, ", Not Authoritative"); } /* Incomplete bit in Map-Referrals */ if (referral) proto_tree_add_item(lisp_mapping_tree, hf_lisp_referral_incomplete, tvb, offset, 2, ENC_BIG_ENDIAN); /* Reserved (11 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_res1, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; if (referral) { /* SigCnt (4 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_referral_sigcnt, tvb, offset, 2, ENC_BIG_ENDIAN); } else { /* Reserved (4 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_res2, tvb, offset, 2, ENC_BIG_ENDIAN); } /* Map-Version Number (12 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_ver, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* EID prefix AFI (16 bits) */ eid_afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_eid_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* EID */ switch (eid_afi) { case AFNUM_INET: proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_eid_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_eid_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: lcaf_prefix_tree = proto_tree_add_subtree_format(lisp_mapping_tree, tvb, offset, addr_len, ett_lisp_lcaf, NULL, "EID Prefix: %s", prefix); dissect_lcaf(tvb, pinfo, lcaf_prefix_tree, offset, NULL); offset += addr_len; break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_eid_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_eid_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; } /* Locators */ for(i=0; i < loc_cnt; i++) { tvbuff_t *loc_tvb; int len = 0; loc_tvb = tvb_new_subset_remaining(tvb, offset); len = dissect_lisp_locator(loc_tvb, pinfo, lisp_mapping_tree, i+1); offset += len; } return offset; } /* * Dissector code for Map-Request type control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=1 |A|M|P|S|p|s| Reserved | IRC | Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Source-EID-AFI | Source EID Address ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ITR-RLOC-AFI 1 | ITR-RLOC Address 1 ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ITR-RLOC-AFI n | ITR-RLOC Address n ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * / | Reserved | EID mask-len | EID-prefix-AFI | * Rec +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \ | EID-prefix ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Map-Reply Record ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static void dissect_lisp_map_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree) { int i; guint16 addr_len = 0; gint offset = 0; guint16 flags; gboolean mrep; gboolean smr; gboolean probe; gboolean pitr; gboolean smr_invoked; guint8 itr_rec_cnt = 0; guint8 rec_cnt = 0; guint16 src_eid_afi; const gchar *src_eid; proto_item *ti_flags; proto_tree *flags_tree, *lcaf_src_eid_tree, *lcaf_prefix_tree; tvbuff_t *next_tvb; /* Flags (6 bits)*/ flags = tvb_get_ntohs(tvb, offset); mrep = flags & (MAP_REQ_FLAG_M >> 8); smr = flags & (MAP_REQ_FLAG_S >> 8); probe = flags & (MAP_REQ_FLAG_P >> 8); pitr = flags & (MAP_REQ_FLAG_p >> 8); smr_invoked = flags & (MAP_REQ_FLAG_s >> 8); ti_flags = proto_tree_add_item(lisp_tree, hf_lisp_mreq_flags, tvb, offset, 3, ENC_BIG_ENDIAN); flags_tree = proto_item_add_subtree(ti_flags, ett_lisp_mreq_flags); proto_tree_add_item(flags_tree, hf_lisp_mreq_flags_auth, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_mreq_flags_mrp, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_mreq_flags_probe, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_mreq_flags_smr, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_mreq_flags_pitr, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(flags_tree, hf_lisp_mreq_flags_smri, tvb, offset, 3, ENC_BIG_ENDIAN); if (pitr) col_append_str(pinfo->cinfo, COL_INFO, " by P-ITR"); if (smr) col_append_str(pinfo->cinfo, COL_INFO, " (SMR)"); if (probe) col_append_str(pinfo->cinfo, COL_INFO, " (RLOC-probe)"); if (smr_invoked) col_append_str(pinfo->cinfo, COL_INFO, " (SMR-invoked)"); /* Reserved bits (9 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_mreq_res, tvb, offset, 3, ENC_BIG_ENDIAN); /* ITR record count (5 bits) */ itr_rec_cnt = tvb_get_guint8(tvb, offset + 2) & 0x1F; proto_tree_add_item(lisp_tree, hf_lisp_irc, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; /* Record count (8 bits) */ rec_cnt = tvb_get_guint8(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_records, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Nonce (64 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_nonce, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Source EID AFI (16 bits) */ src_eid_afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_mreq_srceid_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Source EID */ switch (src_eid_afi) { case AFNUM_RESERVED: proto_tree_add_string(lisp_tree, hf_lisp_mreq_srceid_string, tvb, offset, 0, "not set"); break; case AFNUM_INET: proto_tree_add_item(lisp_tree, hf_lisp_mreq_srceid_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(lisp_tree, hf_lisp_mreq_srceid_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: src_eid = get_addr_str(pinfo->pool, tvb, offset, src_eid_afi, &addr_len); lcaf_src_eid_tree = proto_tree_add_subtree_format(lisp_tree, tvb, offset, addr_len, ett_lisp_lcaf, NULL, "Source EID: %s", src_eid); dissect_lcaf(tvb, pinfo, lcaf_src_eid_tree, offset, NULL); offset += addr_len; break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(lisp_tree, hf_lisp_mreq_srceid_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; default: expert_add_info_format(pinfo, lisp_tree, &ei_lisp_unexpected_field, "Unexpected Source EID AFI (%d), cannot decode", src_eid_afi); next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); return; } /* ITR records */ for(i=0; i < itr_rec_cnt+1; i++) { guint16 itr_afi; proto_item *tir; proto_tree *lisp_itr_tree; itr_afi = tvb_get_ntohs(tvb, offset); tir = proto_tree_add_item(lisp_tree, hf_lisp_mreq_itr_rloc, tvb, offset, 2, ENC_NA); lisp_itr_tree = proto_item_add_subtree(tir, ett_lisp_itr); proto_tree_add_item(lisp_itr_tree, hf_lisp_mreq_itr_rloc_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; switch (itr_afi) { case AFNUM_INET: proto_tree_add_item(lisp_itr_tree, hf_lisp_mreq_itr_rloc_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); proto_item_append_text(tir, " %d: %s", i + 1, tvb_ip_to_str(pinfo->pool, tvb, offset)); proto_item_set_len(tir, 2 + INET_ADDRLEN); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(lisp_itr_tree, hf_lisp_mreq_itr_rloc_ipv6, tvb, offset, 16, ENC_NA); proto_item_append_text(tir, " %d: %s", i + 1, tvb_ip6_to_str(pinfo->pool, tvb, offset)); proto_item_set_len(tir, 2 + INET6_ADDRLEN); offset += INET6_ADDRLEN; break; default: expert_add_info_format(pinfo, lisp_tree, &ei_lisp_unexpected_field, "Unexpected ITR-RLOC-AFI (%d), cannot decode", itr_afi); next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); return; } } /* Query records */ for(i=0; i < rec_cnt; i++) { gint str_len; guint16 prefix_mask; guint16 prefix_afi; const gchar *prefix; proto_item *tir; proto_tree *lisp_record_tree; addr_len = 0; prefix_mask = tvb_get_guint8(tvb, offset + 1); prefix_afi = tvb_get_ntohs(tvb, offset + 2); prefix = get_addr_str(pinfo->pool, tvb, offset + 4, prefix_afi, &addr_len); if (prefix == NULL) { expert_add_info_format(pinfo, lisp_tree, &ei_lisp_unexpected_field, "Unexpected EID prefix AFI (%d), cannot decode", prefix_afi); next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); return; } tir = proto_tree_add_item(lisp_tree, hf_lisp_mreq_record, tvb, offset, 4+addr_len, ENC_NA); /* Update the INFO column if there is only one record */ if (rec_cnt == 1) col_append_fstr(pinfo->cinfo, COL_INFO, " for %s/%d", prefix, prefix_mask); lisp_record_tree = proto_item_add_subtree(tir, ett_lisp_record); proto_tree_add_item(lisp_record_tree, hf_lisp_mreq_record_res, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(lisp_record_tree, hf_lisp_mreq_record_prefix_length, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(lisp_record_tree, hf_lisp_mreq_record_prefix_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; switch (prefix_afi) { case AFNUM_INET: proto_tree_add_item(lisp_record_tree, hf_lisp_mreq_record_prefix_ipv4, tvb, offset, INET_ADDRLEN, ENC_NA); offset += INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(lisp_record_tree, hf_lisp_mreq_record_prefix_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); offset += INET6_ADDRLEN; break; case AFNUM_LCAF: lcaf_prefix_tree = proto_tree_add_subtree_format(lisp_record_tree, tvb, offset, addr_len, ett_lisp_lcaf, NULL, "Prefix: %s", prefix); dissect_lcaf(tvb, pinfo, lcaf_prefix_tree, offset, NULL); offset += addr_len; break; case AFNUM_802: case AFNUM_EUI48: proto_tree_add_item(lisp_record_tree, hf_lisp_mreq_record_prefix_mac, tvb, offset, EUI48_ADDRLEN, ENC_NA); offset += EUI48_ADDRLEN; break; case AFNUM_DISTNAME: str_len = tvb_strsize(tvb, offset); proto_tree_add_item(lisp_record_tree, hf_lisp_mreq_record_prefix_dn, tvb, offset, str_len, ENC_ASCII); offset += str_len; break; } proto_item_append_text(tir, " %d: %s/%d", i+1, prefix, prefix_mask); } /* If M bit is set, we also have a Map-Reply */ if (mrep) { proto_item *tim; proto_tree *lisp_mr_tree; tim = proto_tree_add_item(lisp_tree, hf_lisp_mrep_record, tvb, offset, -1, ENC_NA); lisp_mr_tree = proto_item_add_subtree(tim, ett_lisp_mr); offset = dissect_lisp_mapping(tvb, pinfo, lisp_mr_tree, 0, 1, FALSE, offset, NULL); } next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); } /* * Dissector code for Map-Reply type control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=2 |P|E|S| Reserved | Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Locator Count | EID mask-len | ACT |A| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c | Rsvd | Map-Version Number | EID-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | o | Unused Flags |L|p|R| Loc-AFI | * | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static void dissect_lisp_map_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree) { int i; gint offset = 0; gboolean probe; guint8 flags; guint8 rec_cnt = 0; tvbuff_t *next_tvb; /* Flags (2 bits) */ flags = tvb_get_guint8(tvb, offset); probe = flags & (MAP_REP_FLAG_P >> 16); proto_tree_add_item(lisp_tree, hf_lisp_mrep_flags_probe, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mrep_flags_enlr, tvb, offset, 3, ENC_BIG_ENDIAN); /* Flags defined in LISP-SEC draft (1 bit) */ proto_tree_add_item(lisp_tree, hf_lisp_mrep_flags_sec, tvb, offset, 3, ENC_BIG_ENDIAN); if (probe) col_append_str(pinfo->cinfo, COL_INFO, " (RLOC-probe reply)"); /* Reserved bits (18 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_mrep_res, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; /* Record count (8 bits) */ rec_cnt = tvb_get_guint8(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_records, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Nonce (64 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_nonce, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Reply records */ for(i=0; i < rec_cnt; i++) { offset = dissect_lisp_mapping(tvb, pinfo, lisp_tree, rec_cnt, i+1, FALSE, offset, NULL); } next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); } /* * Dissector code for Map-Register type control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=3 |P|S|I|R| Reserved |M| Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Locator Count | EID mask-len | ACT |A| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c | Rsvd | Map-Version Number | EID-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | o | Unused Flags |L|p|R| Loc-AFI | * | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ gint dissect_lisp_map_register(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree, gint offset, proto_item *tim, gboolean keep_going) { int i; guint8 rec_cnt = 0; tvbuff_t *next_tvb; guint16 authlen = 0; guint16 flags; gboolean xtrid; gboolean rtr; /* Flags (1 bit) */ proto_tree_add_item(lisp_tree, hf_lisp_mreg_flags_pmr, tvb, offset, 3, ENC_BIG_ENDIAN); /* Flags defined in LISP-SEC draft (1 bit) */ proto_tree_add_item(lisp_tree, hf_lisp_mreg_flags_sec, tvb, offset, 3, ENC_BIG_ENDIAN); /* Flags defined in NAT Traversal draft (2 bits) */ flags = tvb_get_ntohs(tvb, offset); xtrid = flags & (MAP_REG_FLAG_I >> 8); rtr = flags & (MAP_REG_FLAG_R >> 8); proto_tree_add_item(lisp_tree, hf_lisp_mreg_flags_xtrid, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mreg_flags_rtr, tvb, offset, 3, ENC_BIG_ENDIAN); if (rtr) col_append_str(pinfo->cinfo, COL_INFO, " (RTR)"); /* Reserved bits (15 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_mreg_res, tvb, offset, 3, ENC_BIG_ENDIAN); /* Flags (1 bit) */ proto_tree_add_item(lisp_tree, hf_lisp_mreg_flags_wmn, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; /* Record count (8 bits) */ rec_cnt = tvb_get_guint8(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_records, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Nonce (64 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_nonce, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Key ID (16 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_keyid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Authentication Data Length (16 bits) */ authlen = tvb_get_ntohs(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_authlen, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Authentication Data */ /* XXX: need to check is there is still enough data in buffer */ proto_tree_add_item(lisp_tree, hf_lisp_auth, tvb, offset, authlen, ENC_NA); offset += authlen; for(i=0; i < rec_cnt; i++) { offset = dissect_lisp_mapping(tvb, pinfo, lisp_tree, rec_cnt, i+1, FALSE, offset, tim); } /* If I bit is set, we have an xTR-ID and a site-ID field */ if (xtrid) { proto_tree_add_item(lisp_tree, hf_lisp_xtrid, tvb, offset, LISP_XTRID_LEN, ENC_NA); proto_tree_add_item(lisp_tree, hf_lisp_siteid, tvb, offset + LISP_XTRID_LEN, LISP_SITEID_LEN, ENC_NA); offset += LISP_XTRID_LEN + LISP_SITEID_LEN; } if (keep_going) { next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); } else { return offset; } return 0; } /* * Dissector code for Map-Notify type control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=4 |I|R| Reserved | Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Locator Count | EID mask-len | ACT |A| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c | Rsvd | Map-Version Number | EID-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | o | Unused Flags |L|p|R| Loc-AFI | * | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static void dissect_lisp_map_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree) { int i; gint offset = 0; guint8 rec_cnt = 0; tvbuff_t *next_tvb; guint16 authlen = 0; guint16 flags; gboolean xtrid; gboolean rtr; /* Flags defined in NAT Traversal draft (2 bits) */ flags = tvb_get_ntohs(tvb, offset); xtrid = flags & (MAP_NOT_FLAG_I >> 8); rtr = flags & (MAP_NOT_FLAG_R >> 8); proto_tree_add_item(lisp_tree, hf_lisp_mnot_flags_xtrid, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mnot_flags_rtr, tvb, offset, 3, ENC_BIG_ENDIAN); if (rtr) col_append_str(pinfo->cinfo, COL_INFO, " (RTR)"); /* Reserved bits (18 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_mnot_res, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; /* Record count (8 bits) */ rec_cnt = tvb_get_guint8(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_records, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Nonce (64 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_nonce, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Key ID (16 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_keyid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Authentication Data Length (16 bits) */ authlen = tvb_get_ntohs(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_authlen, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Authentication Data */ /* XXX: need to check is there is still enough data in buffer */ proto_tree_add_item(lisp_tree, hf_lisp_auth, tvb, offset, authlen, ENC_NA); offset += authlen; for(i=0; i < rec_cnt; i++) { offset = dissect_lisp_mapping(tvb, pinfo, lisp_tree, rec_cnt, i+1, FALSE, offset, NULL); } /* If I bit is set, we have an xTR-ID and a site-ID field */ if (xtrid) { proto_tree_add_item(lisp_tree, hf_lisp_xtrid, tvb, offset, LISP_XTRID_LEN, ENC_NA); proto_tree_add_item(lisp_tree, hf_lisp_siteid, tvb, offset + LISP_XTRID_LEN, LISP_SITEID_LEN, ENC_NA); offset += LISP_XTRID_LEN + LISP_SITEID_LEN; } /* If R bit is set, we have MS-RTR authentication data */ if (rtr) { /* MS-RTR Key ID (16 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_msrtr_keyid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* MS-RTR Authentication Data Length (16 bits) */ authlen = tvb_get_ntohs(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_msrtr_authlen, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* MS-RTR Authentication Data */ /* XXX: need to check is there is still enough data in buffer */ proto_tree_add_item(lisp_tree, hf_lisp_msrtr_auth, tvb, offset, authlen, ENC_NA); offset += authlen; } next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); } /* * Dissector code for Map-Referral type control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=6 | Reserved | Record Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | Record TTL | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * R | Referral Count| EID mask-len | ACT |A|I| Reserved | * e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * c |SigCnt | Map Version Number | EID-AFI | * o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * r | EID-prefix ... | * d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | /| Priority | Weight | M Priority | M Weight | * | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | o | Unused Flags |R| Loc/LCAF-AFI | * | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | \| Locator ... | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static void dissect_lisp_map_referral(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree) { int i; gint offset = 0; guint8 rec_cnt = 0; tvbuff_t *next_tvb; /* Reserved bits (20 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_mref_res, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; /* Record count (8 bits) */ rec_cnt = tvb_get_guint8(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_records, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Nonce (64 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_nonce, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Referral records */ for(i=0; i < rec_cnt; i++) { offset = dissect_lisp_mapping(tvb, pinfo, lisp_tree, rec_cnt, i+1, TRUE, offset, NULL); } next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); } /* * Dissector code for Info type control packets * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=7 |R| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Nonce . . . | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | . . . Nonce | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key ID | Authentication Data Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ~ Authentication Data ~ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | TTL | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved | EID mask-len | EID-prefix-AFI | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | EID-prefix | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | AFI | ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static void dissect_lisp_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree) { gint offset = 0; tvbuff_t *next_tvb; guint8 flags; gboolean reply; guint16 authlen = 0; guint8 prefix_mask; guint16 prefix_afi, afi; const gchar *prefix; guint16 addr_len = 0; proto_item *tir, *ti_prefix; proto_tree *prefix_tree; /* Flags (1 bit) */ flags = tvb_get_guint8(tvb, offset); reply = flags & (INFO_FLAG_R >> 16); if (reply) col_append_str(pinfo->cinfo, COL_INFO, "-Reply"); else col_append_str(pinfo->cinfo, COL_INFO, "-Request"); proto_tree_add_item(lisp_tree, hf_lisp_info_r, tvb, offset, 3, ENC_BIG_ENDIAN); /* Reserved bits (27 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_info_res1, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Nonce (64 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_nonce, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Key ID (16 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_keyid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Authentication Data Length (16 bits) */ authlen = tvb_get_ntohs(tvb, offset); proto_tree_add_item(lisp_tree, hf_lisp_authlen, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Authentication Data */ /* XXX: need to check is there is still enough data in buffer */ proto_tree_add_item(lisp_tree, hf_lisp_auth, tvb, offset, authlen, ENC_NA); offset += authlen; /* TTL */ proto_tree_add_item(lisp_tree, hf_lisp_info_ttl, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Reserved bits (8 bits) */ proto_tree_add_item(lisp_tree, hf_lisp_info_res2, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; prefix_tree = proto_tree_add_subtree(lisp_tree, tvb, offset, 3, ett_lisp_info_prefix, &ti_prefix, "EID Prefix: "); proto_tree_add_item(prefix_tree, hf_lisp_info_prefix_masklen, tvb, offset, 1, ENC_BIG_ENDIAN); prefix_mask = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(prefix_tree, hf_lisp_info_prefix_afi, tvb, offset, 2, ENC_BIG_ENDIAN); prefix_afi = tvb_get_ntohs(tvb, offset); offset += 2; prefix = get_addr_str(pinfo->pool, tvb, offset, prefix_afi, &addr_len); if (prefix == NULL) { expert_add_info_format(pinfo, lisp_tree, &ei_lisp_unexpected_field, "Unexpected EID prefix AFI (%d), cannot decode", prefix_afi); next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); return; } switch (prefix_afi) { case AFNUM_INET: proto_tree_add_item(prefix_tree, hf_lisp_info_prefix_ipv4, tvb, offset, INET_ADDRLEN, ENC_BIG_ENDIAN); break; case AFNUM_INET6: proto_tree_add_item(prefix_tree, hf_lisp_info_prefix_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); break; } proto_item_append_text(ti_prefix, "%s/%d", prefix, prefix_mask); proto_item_set_len(ti_prefix, 3 + addr_len); offset += addr_len; /* Update the INFO column */ col_append_fstr(pinfo->cinfo, COL_INFO, " for %s/%d", prefix, prefix_mask); tir = proto_tree_add_item(lisp_tree, hf_lisp_info_afi, tvb, offset, 2, ENC_BIG_ENDIAN); afi = tvb_get_ntohs(tvb, offset); offset += 2; if (!reply) { if (afi != 0) { expert_add_info_format(pinfo, tir, &ei_lisp_expected_field, "Expecting NULL AFI (0), found %d, incorrect packet!", afi); } } else { if (afi != AFNUM_LCAF) { expert_add_info_format(pinfo, tir, &ei_lisp_expected_field, "Expecting LCAF AFI (%d), found %d, incorrect packet!", AFNUM_LCAF, afi); } else { offset = dissect_lcaf(tvb, pinfo, lisp_tree, offset, NULL); } } next_tvb = tvb_new_subset_remaining(tvb, offset); call_data_dissector(next_tvb, pinfo, lisp_tree); } /* * Dissector code for Encapsulated Control Message type packets * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=8 |S|D| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | IPv4 or IPv6 Header | * | (uses RLOC or EID addresses) | * ~ ~ * */ static void dissect_lisp_ecm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *lisp_tree) { tvbuff_t *next_tvb; guint8 flags; guint8 ip_ver; /* Flags (2 bits) */ flags = tvb_get_guint8(tvb, 0); ddt_originated = flags & (ECM_FLAG_D >> 24); proto_tree_add_item(lisp_tree, hf_lisp_ecm_flags_sec, tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_ecm_flags_ddt, tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_ecm_res, tvb, 0, 4, ENC_BIG_ENDIAN); /* Determine if encapsulated packet is IPv4 or IPv6, and call dissector */ next_tvb = tvb_new_subset_remaining(tvb, LISP_ECM_HEADER_LEN); ip_ver = tvb_get_bits8(next_tvb, 0, 4); switch (ip_ver) { case 4: call_dissector(ipv4_handle, next_tvb, pinfo, tree); break; case 6: call_dissector(ipv6_handle, next_tvb, pinfo, tree); break; default: call_data_dissector(next_tvb, pinfo, tree); break; } encapsulated = FALSE; } /* * Main dissector code */ static int dissect_lisp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { guint8 type; proto_tree *lisp_tree = NULL; /* Clear Info column before fetching data in case an exception is thrown */ col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_bits8(tvb, 0, 4); /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LISP"); if (encapsulated) { col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated %s", val_to_str(type, lisp_typevals, "Unknown LISP Control Packet (%d)")); } else { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, lisp_typevals, "Unknown LISP Control Packet (%d)")); } if (ddt_originated) { col_append_str(pinfo->cinfo, COL_INFO, " (DDT-originated)"); ddt_originated = FALSE; } if (tree) { proto_item *ti; /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_lisp, tvb, 0, (type == LISP_ECM) ? LISP_ECM_HEADER_LEN : -1, ENC_NA); lisp_tree = proto_item_add_subtree(ti, ett_lisp); proto_tree_add_item(lisp_tree, hf_lisp_type, tvb, 0, 3, ENC_BIG_ENDIAN); } /* Sub-dissectors are indirectly called by the following and thus this code should be executed whether or not tree==NULL. */ switch (type) { case LISP_MAP_REQUEST: dissect_lisp_map_request(tvb, pinfo, lisp_tree); break; case LISP_MAP_REPLY: dissect_lisp_map_reply(tvb, pinfo, lisp_tree); break; case LISP_MAP_REGISTER: dissect_lisp_map_register(tvb, pinfo, lisp_tree, 0, NULL, TRUE); break; case LISP_MAP_NOTIFY: dissect_lisp_map_notify(tvb, pinfo, lisp_tree); break; case LISP_MAP_REFERRAL: dissect_lisp_map_referral(tvb, pinfo, lisp_tree); break; case LISP_INFO: dissect_lisp_info(tvb, pinfo, lisp_tree); break; case LISP_ECM: encapsulated = TRUE; dissect_lisp_ecm(tvb, pinfo, tree, lisp_tree); break; default: call_data_dissector(tvb, pinfo, tree); break; } /* Return the amount of data this dissector was able to dissect */ return tvb_reported_length(tvb); } /* * Register the LISP protocol with Wireshark */ void proto_register_lisp(void) { /* Setup list of header fields */ static hf_register_info hf[] = { { &hf_lisp_type, { "Type", "lisp.type", FT_UINT24, BASE_DEC, VALS(lisp_typevals), 0xF00000, "LISP Control Message Type", HFILL }}, { &hf_lisp_irc, { "ITR-RLOC Count", "lisp.irc", FT_UINT24, BASE_DEC, NULL, 0x00001F, NULL, HFILL }}, { &hf_lisp_records, { "Record Count", "lisp.records", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_nonce, { "Nonce", "lisp.nonce", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_flags, { "Flags", "lisp.mreq.flags", FT_UINT24, BASE_HEX, NULL, 0x0FC000, NULL, HFILL }}, { &hf_lisp_mreq_flags_auth, { "A bit (Authoritative)", "lisp.mreq.flags.auth", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REQ_FLAG_A, NULL, HFILL }}, { &hf_lisp_mreq_flags_mrp, { "M bit (Map-Reply present)", "lisp.mreq.flags.mrp", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REQ_FLAG_M, NULL, HFILL }}, { &hf_lisp_mreq_flags_probe, { "P bit (Probe)", "lisp.mreq.flags.probe", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REQ_FLAG_P, NULL, HFILL }}, { &hf_lisp_mreq_flags_smr, { "S bit (Solicit-Map-Request)", "lisp.mreq.flags.smr", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REQ_FLAG_S, NULL, HFILL }}, { &hf_lisp_mreq_flags_pitr, { "p bit (Proxy ITR)", "lisp.mreq.flags.pitr", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REQ_FLAG_p, NULL, HFILL }}, { &hf_lisp_mreq_flags_smri, { "s bit (SMR-invoked)", "lisp.mreq.flags.smri", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REQ_FLAG_s, NULL, HFILL }}, { &hf_lisp_mreq_res, { "Reserved bits", "lisp.mreq.res", FT_UINT24, BASE_HEX, NULL, MAP_REQ_RESERVED, "Must be zero", HFILL }}, { &hf_lisp_mreq_srceid_afi, { "Source EID AFI", "lisp.mreq.srceid.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Source EID Address Family Indicator", HFILL }}, { &hf_lisp_mreq_srceid_string, { "Source EID", "lisp.mreq.srceid.string", FT_STRING, BASE_NONE, NULL, 0x0, "Source EID Address", HFILL }}, { &hf_lisp_mreq_srceid_ipv4, { "Source EID", "lisp.mreq.srceid.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, "Source EID Address", HFILL }}, { &hf_lisp_mreq_srceid_ipv6, { "Source EID", "lisp.mreq.srceid_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, "Source EID Address", HFILL }}, { &hf_lisp_mreq_srceid_mac, { "Source EID", "lisp.mreq.srceid.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_itr_rloc, { "ITR-RLOC", "lisp.mreq.itr_rloc", FT_NONE, BASE_NONE, NULL, 0x0, "Originating ITR RLOC Address", HFILL }}, { &hf_lisp_mreq_itr_rloc_afi, { "ITR-RLOC AFI", "lisp.mreq.itr_rloc.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Originating ITR RLOC Address Family Indicator", HFILL }}, { &hf_lisp_mreq_itr_rloc_ipv4, { "ITR-RLOC Address", "lisp.mreq.itr_rloc_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, "Originating ITR RLOC Address", HFILL }}, { &hf_lisp_mreq_itr_rloc_ipv6, { "ITR-RLOC Address", "lisp.mreq.itr_rloc_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, "Originating ITR RLOC Address", HFILL }}, { &hf_lisp_mreq_record_res, { "Reserved", "lisp.mreq.record.res", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_record_prefix_length, { "Prefix Length", "lisp.mreq.record.prefix.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_record_prefix_afi, { "Prefix AFI", "lisp.mreq.record.prefix.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_mreq_record_prefix_ipv4, { "Prefix", "lisp.mreq.record.prefix.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_record_prefix_ipv6, { "Prefix", "lisp.mreq.record.prefix.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_record_prefix_mac, { "Prefix", "lisp.mreq.record.prefix.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_record_prefix_dn, { "Prefix", "lisp.mreq.record.prefix.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreq_record, { "Map-Request Record", "lisp.mreq.record", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mrep_record, { "Map-Reply Record", "lisp.mrep.record", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mrep_flags_probe, { "P bit (Probe)", "lisp.mrep.flags.probe", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REP_FLAG_P, NULL, HFILL }}, { &hf_lisp_mrep_flags_enlr, { "E bit (Echo-Nonce locator reachability algorithm enabled)", "lisp.mrep.flags.enlr", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REP_FLAG_E, NULL, HFILL }}, { &hf_lisp_mrep_flags_sec, { "S bit (LISP-SEC capable)", "lisp.mrep.flags.sec", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REP_FLAG_S, NULL, HFILL }}, { &hf_lisp_mrep_res, { "Reserved bits", "lisp.mrep.res", FT_UINT24, BASE_HEX, NULL, MAP_REP_RESERVED, "Must be zero", HFILL }}, { &hf_lisp_mreg_flags_pmr, { "P bit (Proxy-Map-Reply)", "lisp.mreg.flags.pmr", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REG_FLAG_P, NULL, HFILL }}, { &hf_lisp_mreg_flags_sec, { "S bit (LISP-SEC capable)", "lisp.mreg.flags.sec", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REG_FLAG_S, NULL, HFILL }}, { &hf_lisp_mreg_flags_xtrid, { "I bit (xTR-ID present)", "lisp.mreg.flags.xtrid", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REG_FLAG_I, NULL, HFILL }}, { &hf_lisp_mreg_flags_rtr, { "R bit (Built for an RTR)", "lisp.mreg.flags.rtr", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REG_FLAG_R, NULL, HFILL }}, { &hf_lisp_mreg_flags_wmn, { "M bit (Want-Map-Notify)", "lisp.mreg.flags.wmn", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_REG_FLAG_M, NULL, HFILL }}, { &hf_lisp_mreg_res, { "Reserved bits", "lisp.mreg.res", FT_UINT24, BASE_HEX, NULL, MAP_REG_RESERVED, "Must be zero", HFILL }}, { &hf_lisp_mref_res, { "Reserved bits", "lisp.mref.res", FT_UINT24, BASE_HEX, NULL, MAP_REF_RESERVED, "Must be zero", HFILL }}, { &hf_lisp_keyid, { "Key ID", "lisp.keyid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_authlen, { "Authentication Data Length", "lisp.authlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_auth, { "Authentication Data", "lisp.auth", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_msrtr_keyid, { "MS-RTR Key ID", "lisp.msrtr.keyid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_msrtr_authlen, { "MS-RTR Authentication Data Length", "lisp.msrtr.authlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_msrtr_auth, { "MS-RTR Authentication Data", "lisp.msrtr.auth", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_xtrid, { "xTR-ID", "lisp.xtrid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_siteid, { "Site-ID", "lisp.siteid", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mnot_flags_xtrid, { "I bit (xTR-ID present)", "lisp.mnot.flags.xtrid", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_NOT_FLAG_I, NULL, HFILL }}, { &hf_lisp_mnot_flags_rtr, { "R bit (Built for an RTR)", "lisp.mnot.flags.rtr", FT_BOOLEAN, 24, TFS(&tfs_set_notset), MAP_NOT_FLAG_R, NULL, HFILL }}, { &hf_lisp_mnot_res, { "Reserved bits", "lisp.mnot.res", FT_UINT24, BASE_HEX, NULL, MAP_NOT_RESERVED, "Must be zero", HFILL }}, { &hf_lisp_info_r, { "R bit (Info-Reply)", "lisp.info.r", FT_BOOLEAN, 24, TFS(&tfs_set_notset), INFO_FLAG_R, NULL, HFILL }}, { &hf_lisp_info_res1, { "Reserved bits", "lisp.info.res1", FT_UINT32, BASE_HEX, NULL, INFO_RESERVED, "Must be zero", HFILL }}, { &hf_lisp_info_ttl, { "TTL", "lisp.info.ttl", FT_UINT32, BASE_DEC, NULL, 0x0, "RTR information time-to-live", HFILL }}, { &hf_lisp_info_res2, { "Reserved bits", "lisp.info.res2", FT_UINT8, BASE_HEX, NULL, 0xFF, "Must be zero", HFILL }}, { &hf_lisp_info_prefix_masklen, { "EID Prefix Mask Length", "lisp.info.prefix.masklen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_info_prefix_afi, { "Prefix AFI", "lisp.info.prefix.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_info_prefix_ipv4, { "Prefix", "lisp.info.prefix.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_info_prefix_ipv6, { "Prefix", "lisp.info.prefix.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_info_afi, { "AFI", "lisp.info.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Address Family Indicator", HFILL }}, { &hf_lisp_loc, { "Locator Record", "lisp.loc", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_loc_priority, { "Priority", "lisp.loc.priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_loc_weight, { "Weight", "lisp.loc.weight", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_loc_mpriority, { "Multicast Priority", "lisp.loc.multicast_priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_loc_mweight, { "Multicast Weight", "lisp.loc.multicast_weight", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_loc_flags, { "Flags", "lisp.loc.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_loc_flags_local, { "Local", "lisp.loc.flags.local", FT_BOOLEAN, 16, TFS(&tfs_set_notset), LOCAL_BIT_MASK, NULL, HFILL }}, { &hf_lisp_loc_flags_probe, { "Probe", "lisp.loc.flags.probe", FT_BOOLEAN, 16, TFS(&tfs_set_notset), PROBE_BIT_MASK, NULL, HFILL }}, { &hf_lisp_loc_flags_reach, { "Reachable", "lisp.loc.flags.reach", FT_BOOLEAN, 16, TFS(&tfs_set_notset), REACH_BIT_MASK, NULL, HFILL }}, { &hf_lisp_loc_flags_res, { "Reserved", "lisp.loc.flags.res", FT_UINT16, BASE_HEX, NULL, 0xFFF8, "Must be zero", HFILL }}, { &hf_lisp_loc_afi, { "AFI", "lisp.loc.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_loc_locator, { "Locator", "lisp.loc.locator", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping, { "Mapping Record", "lisp.mapping", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_ttl, { "Record TTL", "lisp.mapping.ttl", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_loccnt, { "Locator Count", "lisp.mapping.loccnt", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_eid_masklen, { "EID Mask Length", "lisp.mapping.eid.masklen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_act, { "Action", "lisp.mapping.act", FT_UINT16, BASE_DEC, VALS(mapping_actions), 0xE000, NULL, HFILL }}, { &hf_lisp_mapping_auth, { "Authoritative bit", "lisp.mapping.auth", FT_BOOLEAN, 16, TFS(&tfs_set_notset), LISP_MAP_AUTH, NULL, HFILL }}, { &hf_lisp_referral_incomplete, { "Incomplete", "lisp.referral.incomplete", FT_BOOLEAN, 16, TFS(&tfs_set_notset), REFERRAL_INCOMPLETE, NULL, HFILL }}, { &hf_lisp_mapping_res1, { "Reserved", "lisp.mapping.res1", FT_UINT16, BASE_HEX, NULL, 0x07FF, NULL, HFILL }}, { &hf_lisp_mapping_res2, { "Reserved", "lisp.mapping.res2", FT_UINT16, BASE_HEX, NULL, 0xF000, NULL, HFILL }}, { &hf_lisp_mapping_ver, { "Mapping Version", "lisp.mapping.ver", FT_UINT16, BASE_DEC, NULL, 0x0FFF, NULL, HFILL }}, { &hf_lisp_referral_sigcnt, { "Signature Count", "lisp.referral.sigcnt", FT_UINT16, BASE_DEC, NULL, 0xF000, NULL, HFILL }}, { &hf_lisp_mapping_eid_afi, { "EID Prefix AFI", "lisp.mapping.eid.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_mapping_eid_ipv4, { "EID Prefix", "lisp.mapping.eid.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_eid_ipv6, { "EID Prefix", "lisp.mapping.eid.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_eid_mac, { "EID Prefix", "lisp.mapping.eid.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_eid_dn, { "EID Prefix", "lisp.mapping.eid.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_ecm_flags_sec, { "S bit (LISP-SEC capable)", "lisp.ecm.flags.sec", FT_BOOLEAN, 32, TFS(&tfs_set_notset), ECM_FLAG_S, NULL, HFILL }}, { &hf_lisp_ecm_flags_ddt, { "D bit (DDT-originated)", "lisp.ecm.flags.ddt", FT_BOOLEAN, 32, TFS(&tfs_set_notset), ECM_FLAG_D, NULL, HFILL }}, { &hf_lisp_ecm_res, { "Reserved bits", "lisp.ecm.res", FT_UINT32, BASE_HEX, NULL, 0x03FFFFFF, NULL, HFILL }}, { &hf_lisp_lcaf, { "LCAF", "lisp.lcaf", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_header, { "LCAF Header", "lisp.lcaf.header", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_res1, { "Reserved bits", "lisp.lcaf.res1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_flags, { "Flags", "lisp.lcaf.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_type, { "Type", "lisp.lcaf.type", FT_UINT8, BASE_DEC, VALS(lcaf_typevals), 0x0, "LISP LCAF Type", HFILL }}, { &hf_lisp_lcaf_res2, { "Reserved bits", "lisp.lcaf.res2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_length, { "Length", "lisp.lcaf.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_afi_list_item, { "List Item", "lisp.lcaf.afi_list.item", FT_NONE, BASE_NONE, NULL, 0x0, "AFI List Item", HFILL }}, { &hf_lisp_lcaf_afi_list_afi, { "List Item AFI", "lisp.lcaf.afi_list.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_afi_list_ipv4, { "List Item Address", "lisp.lcaf.afi_list.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_afi_list_ipv6, { "List Item Address", "lisp.lcaf.afi_list.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_afi_list_mac, { "List Item Address", "lisp.lcaf.afi_list.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_afi_list_dn, { "List Item Address", "lisp.lcaf.afi_list.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_iid, { "Instance ID", "lisp.lcaf.iid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_iid_afi, { "Address AFI", "lisp.lcaf.iid.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_iid_ipv4, { "Address", "lisp.lcaf.iid.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_iid_ipv6, { "Address", "lisp.lcaf.iid.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_iid_mac, { "Address", "lisp.lcaf.iid.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_iid_dn, { "Address", "lisp.lcaf.iid.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_asn, { "AS Number", "lisp.lcaf.asn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_asn_afi, { "Address AFI", "lisp.lcaf.asn.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_asn_ipv4, { "Address", "lisp.lcaf.asn.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_asn_ipv6, { "Address", "lisp.lcaf.asn.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_asn_mac, { "Address", "lisp.lcaf.asn.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_asn_dn, { "Address", "lisp.lcaf.asn.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lat, { "Latitude", "lisp.lcaf.geo.lat", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lat_hemisphere, { "Hemisphere", "lisp.lcaf.geo.lat.hemisphere", FT_UINT16, BASE_DEC, VALS(lat_typevals), 0x8000, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lat_deg, { "Degrees", "lisp.lcaf.geo.lat.deg", FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lat_min, { "Minutes", "lisp.lcaf.geo.lat.min", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lat_sec, { "Seconds", "lisp.lcaf.geo.lat.sec", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lon, { "Longitude", "lisp.lcaf.geo.lon", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lon_hemisphere, { "Hemisphere", "lisp.lcaf.geo.lon.hemisphere", FT_UINT16, BASE_DEC, VALS(lon_typevals), 0x8000, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lon_deg, { "Degrees", "lisp.lcaf.geo.lon.deg", FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lon_min, { "Minutes", "lisp.lcaf.geo.lon.min", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_lon_sec, { "Seconds", "lisp.lcaf.geo.lon.sec", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_alt, { "Altitude", "lisp.lcaf.geo.alt", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_afi, { "Address AFI", "lisp.lcaf.geo.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_ipv4, { "Address", "lisp.lcaf.geo.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_ipv6, { "Address", "lisp.lcaf.geo.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_mac, { "Address", "lisp.lcaf.geo.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_geo_dn, { "Address", "lisp.lcaf.geo.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_nonce_loc_res, { "Reserved bits", "lisp.lcaf.nonce_loc.res", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_nonce_loc, { "Nonce", "lisp.lcaf.nonce_loc", FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_nonce_loc_afi, { "Address AFI", "lisp.lcaf.nonce_loc.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_nonce_loc_ipv4, { "Address", "lisp.lcaf.nonce_loc.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_nonce_loc_ipv6, { "Address", "lisp.lcaf.nonce_loc.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_nonce_loc_mac, { "Address", "lisp.lcaf.nonce_loc.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_nonce_loc_dn, { "Address", "lisp.lcaf.nonce_loc.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_flags, { "Multicast Info Flags", "lisp.lcaf.mcinfo.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_flags_res, { "Reserved", "lisp.lcaf.mcinfo.flags.res", FT_UINT8, BASE_HEX, NULL, 0xF8, "Must be zero", HFILL }}, { &hf_lisp_lcaf_mcinfo_flags_rp, { "RP-bit", "lisp.lcaf.mcinfo.flags.rp", FT_BOOLEAN, 8, TFS(&tfs_set_notset), MCINFO_FLAG_R, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_flags_leave, { "Leave (L-bit)", "lisp.lcaf.mcinfo.flags.leave", FT_BOOLEAN, 8, TFS(&tfs_set_notset), MCINFO_FLAG_L, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_flags_join, { "Join (J-bit)", "lisp.lcaf_mcinfo.flags.join", FT_BOOLEAN, 8, TFS(&tfs_set_notset), MCINFO_FLAG_J, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_iid, { "Instance ID", "lisp.lcaf.mcinfo_iid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_res, { "Reserved bits", "lisp.lcaf.mcinfo.res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_src_masklen, { "Source Mask Length", "lisp.lcaf.mcinfo.src.masklen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_grp_masklen, { "Group Mask Length", "lisp.lcaf.mcinfo.grp.masklen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_src, { "Source/Subnet Address", "lisp.lcaf.mcinfo.src", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_src_afi, { "Source/Subnet AFI", "lisp.lcaf.mcinfo.src.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_src_ipv4, { "Source/Subnet Address", "lisp.lcaf.mcinfo.src.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_src_ipv6, { "Source/Subnet Address", "lisp.lcaf.mcinfo.src.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_grp, { "Group Address", "lisp.lcaf.mcinfo.grp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_grp_afi, { "Group AFI", "lisp.lcaf.mcinfo.grp.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_grp_ipv4, { "Group Address", "lisp.lcaf.mcinfo.grp.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_mcinfo_grp_ipv6, { "Group Address", "lisp.lcaf.mcinfo.grp.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop, { "Reencap Hop", "lisp.lcaf.elp_hop", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop_flags, { "Flags", "lisp.lcaf.elp_hop.flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop_flags_res, { "Reserved", "lisp.lcaf.elp_hop.flags.res", FT_UINT16, BASE_HEX, NULL, 0xFFF8, "Must be zero", HFILL }}, { &hf_lisp_lcaf_elp_hop_flags_lookup, { "Lookup", "lisp.lcaf.elp_hop.flags.local", FT_BOOLEAN, 16, TFS(&tfs_set_notset), ELP_FLAG_L, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop_flags_probe, { "Probe", "lisp.lcaf.elp_hop.flags.probe", FT_BOOLEAN, 16, TFS(&tfs_set_notset), ELP_FLAG_P, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop_flags_strict, { "Strict", "lisp.lcaf_elp_hop.flags.strict", FT_BOOLEAN, 16, TFS(&tfs_set_notset), ELP_FLAG_S, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop_afi, { "Reencap Hop AFI", "lisp.lcaf.elp_hop.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop_ipv4, { "Reencap Hop", "lisp.lcaf.elp_hop.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_elp_hop_ipv6, { "Reencap Hop", "lisp.lcaf.elp_hop.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_res, { "Reserved bits", "lisp.lcaf.srcdst.res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_src_masklen, { "Source Prefix Mask Length", "lisp.lcaf.srcdst.src.masklen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_dst_masklen, { "Destination Prefix Mask Length", "lisp.lcaf.srcdst.dst.masklen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_src, { "Source Prefix", "lisp.lcaf.srcdst.src", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_src_afi, { "Source Prefix AFI", "lisp.lcaf.srcdst.src.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_src_ipv4, { "Source Prefix", "lisp.lcaf.srcdst.src.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_src_ipv6, { "Source Prefix", "lisp.lcaf.srcdst.src.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_src_mac, { "Destination Prefix", "lisp.lcaf.srcdst.src.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_dst, { "Destination Prefix", "lisp.lcaf.srcdst.dst", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_dst_afi, { "Destination Prefix AFI", "lisp.lcaf.srcdst.dst.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_dst_ipv4, { "Destination Prefix", "lisp.lcaf.srcdst.dst.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_dst_ipv6, { "Destination Prefix", "lisp.lcaf.srcdst.dst.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_srcdst_dst_mac, { "Destination Prefix", "lisp.lcaf.srcdst.dst.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_rle_entry, { "RTR/ETR", "lisp.lcaf.rle_entry", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_rle_entry_res, { "Reserved bits", "lisp.lcaf.rle_entry.res", FT_UINT24, BASE_HEX, NULL, 0x0, "Must be zero", HFILL }}, { &hf_lisp_lcaf_rle_entry_level, { "Level Value", "lisp.lcaf.rle_entry.level", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_rle_entry_afi, { "RTR/ETR AFI", "lisp.lcaf.rle_entry.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_rle_entry_ipv4, { "RTR/ETR", "lisp.lcaf.rle_entry.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_rle_entry_ipv6, { "RTR/ETR", "lisp.lcaf.rle_entry.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_key, { "Key", "lisp.lcaf.kv_key", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_key_afi, { "Key AFI", "lisp.lcaf.kv_key.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_key_ipv4, { "Key", "lisp.lcaf.kv_key.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_key_ipv6, { "Key", "lisp.lcaf.kv_key.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_key_mac, { "Key", "lisp.lcaf.kv_key.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_key_dn, { "Key", "lisp.lcaf.kv_key.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_value, { "Value", "lisp.lcaf.kv_value", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_value_afi, { "Value AFI", "lisp.lcaf.kv_value.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_value_ipv4, { "Value", "lisp.lcaf.kv_value.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_value_ipv6, { "Value", "lisp.lcaf.kv_value.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_value_mac, { "Value", "lisp.lcaf.kv_value.mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_kv_value_dn, { "Value", "lisp.lcaf.kv_value.dn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_natt_rloc, { "RLOC", "lisp.lcaf.natt.rloc", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_natt_rloc_afi, { "RLOC AFI", "lisp.lcaf.natt.rloc.afi", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_natt_rloc_ipv4, { "RLOC", "lisp.lcaf.natt.rloc.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_natt_rloc_ipv6, { "RLOC", "lisp.lcaf.natt.rloc.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_natt_msport, { "MS UDP Port Number", "lisp.lcaf.natt.msport", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_natt_etrport, { "ETR UDP Port Number", "lisp.lcaf.natt.etrport", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_lcaf_vendor_res, { "Reserved", "lisp.lcaf.vendor.res", FT_UINT8, BASE_HEX, NULL, 0x0, "Must be zero", HFILL }}, { &hf_lisp_lcaf_vendor_oui, { "OUI", "lisp.lcaf.vendor.oui", FT_UINT24, BASE_HEX, VALS(oui_vals), 0x0, "Organizationally Unique Identifier", HFILL }}, { &hf_lisp_lcaf_vendor_data, { "Vendor Specific Data", "lisp.lcaf.vendor.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_lisp, &ett_lisp_mr, &ett_lisp_mreq_flags, &ett_lisp_mapping, &ett_lisp_itr, &ett_lisp_record, &ett_lisp_lcaf, &ett_lisp_lcaf_header, &ett_lisp_lcaf_geo_lat, &ett_lisp_lcaf_geo_lon, &ett_lisp_lcaf_natt_rloc, &ett_lisp_lcaf_mcinfo_flags, &ett_lisp_lcaf_mcinfo_src, &ett_lisp_lcaf_mcinfo_grp, &ett_lisp_lcaf_elp_hop, &ett_lisp_lcaf_elp_hop_flags, &ett_lisp_lcaf_srcdst_src, &ett_lisp_lcaf_srcdst_dst, &ett_lisp_lcaf_rle_entry, &ett_lisp_lcaf_kv_key, &ett_lisp_lcaf_kv_value, &ett_lisp_lcaf_vendor, &ett_lisp_loc, &ett_lisp_loc_flags, &ett_lisp_info_prefix, &ett_lisp_afi_list }; static ei_register_info ei[] = { { &ei_lisp_undecoded, { "lisp.undecoded", PI_UNDECODED, PI_WARN, "Not dissected yet (report to wireshark.org)", EXPFILL }}, { &ei_lisp_unexpected_field, { "lisp.unexpected_field", PI_PROTOCOL, PI_ERROR, "Unexpected field", EXPFILL }}, { &ei_lisp_invalid_field, { "lisp.invalid_field", PI_PROTOCOL, PI_WARN, "Invalid field", EXPFILL }}, { &ei_lisp_expected_field, { "lisp.expected_field", PI_PROTOCOL, PI_ERROR, "Expecting field", EXPFILL }}, }; expert_module_t* expert_lisp; /* Register the protocol name and description */ proto_lisp = proto_register_protocol("Locator/ID Separation Protocol", "LISP Control", "lisp"); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_lisp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); expert_lisp = expert_register_protocol(proto_lisp); expert_register_field_array(expert_lisp, ei, array_length(ei)); /* Register dissector so that other dissectors can call it */ lisp_handle = register_dissector("lisp", dissect_lisp, proto_lisp); } /* * Simple form of proto_reg_handoff_lisp which can be used if there are * no prefs-dependent registration function calls. */ void proto_reg_handoff_lisp(void) { dissector_add_uint_with_preference("udp.port", LISP_CONTROL_PORT, lisp_handle); ipv4_handle = find_dissector_add_dependency("ip", proto_lisp); ipv6_handle = find_dissector_add_dependency("ipv6", proto_lisp); } /* * Editor modelines - https://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: */