/* packet-lisp.c * Routines for LISP Control Message dissection * Copyright 2011, Lorand Jakab * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #define INET_ADDRLEN 4 #define INET6_ADDRLEN 16 /* See draft-ietf-lisp-11 "Locator/ID Separation Protocol (LISP)" */ #define LISP_CONTROL_PORT 4342 /* 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_ECM 8 #define LISP_ECM_HEADER_LEN 4 #define LISP_MAP_ACT 0xE0 #define LISP_MAP_AUTH 0x10 #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_RESERVED 0x03FFFF #define MAP_REG_FLAG_P 0x080000 #define MAP_REG_RESERVED 0x07FFFE #define MAP_REG_FLAG_M 0x000001 #define MAP_NOT_RESERVED 0x0FFFFF /* 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; /* Map-Request fields */ 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 = -1; static int hf_lisp_mreq_srceidv6 = -1; static int hf_lisp_mreq_srcitr = -1; static int hf_lisp_mreq_srcitrv6 = -1; /* Map-Reply fields */ static int hf_lisp_mrep_flags = -1; static int hf_lisp_mrep_flags_probe = -1; static int hf_lisp_mrep_flags_enlr = -1; static int hf_lisp_mrep_res = -1; /* Map-Register fields */ static int hf_lisp_mreg_flags = -1; static int hf_lisp_mreg_flags_pmr = -1; static int hf_lisp_mreg_flags_wmn = -1; static int hf_lisp_mreg_res = -1; static int hf_lisp_mreg_keyid = -1; static int hf_lisp_mreg_authlen = -1; static int hf_lisp_mreg_auth = -1; /* Map-Notify fields */ static int hf_lisp_mnot_res = -1; static int hf_lisp_mnot_keyid = -1; static int hf_lisp_mnot_authlen = -1; static int hf_lisp_mnot_auth = -1; /* Mapping record fields */ static int hf_lisp_mapping_res = -1; static int hf_lisp_mapping_ver = -1; /* Encapsulated Control Message fields */ 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_mapping = -1; static gint ett_lisp_itr = -1; static gint ett_lisp_record = -1; static dissector_handle_t ipv4_handle; static dissector_handle_t ipv6_handle; static dissector_handle_t data_handle; static gboolean encapsulated = FALSE; 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_ECM, "Encapsulated Control Message" }, { 0, NULL} }; /* * 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) { gint offset = 0; guint8 prio, weight, m_prio, m_weight; guint16 flags, loc_afi; guint32 locator_v4; struct e_in6_addr locator_v6; tvbuff_t *next_tvb; prio = tvb_get_guint8(tvb, offset); offset += 1; weight = tvb_get_guint8(tvb, offset); offset += 1; m_prio = tvb_get_guint8(tvb, offset); offset += 1; m_weight = tvb_get_guint8(tvb, offset); offset += 1; flags = tvb_get_ntohs(tvb, offset); offset += 2; loc_afi = tvb_get_ntohs(tvb, offset); offset += 2; switch (loc_afi) { case AFNUM_INET: locator_v4 = tvb_get_ipv4(tvb, offset); proto_tree_add_text(lisp_mapping_tree, tvb, 0, 8 + INET_ADDRLEN, "%sRLOC: %s%s, %s, Priority/Weight: %d/%d, Multicast Priority/Weight: %d/%d", (flags&LOCAL_BIT_MASK) ? "Local " : "", ip_to_str((guint8 *)&locator_v4), (flags&PROBE_BIT_MASK) ? " (probed)" : "", (flags&REACH_BIT_MASK) ? "Reachable" : "Unreachable", prio, weight, m_prio, m_weight); offset += INET_ADDRLEN; break; case AFNUM_INET6: tvb_get_ipv6(tvb, offset, &locator_v6); proto_tree_add_text(lisp_mapping_tree, tvb, 0, 8 + INET6_ADDRLEN, "%sRLOC: %s%s, %s, Priority/Weight: %d/%d, Multicast Priority/Weight: %d/%d", (flags&LOCAL_BIT_MASK) ? "Local " : "", ip6_to_str(&locator_v6), (flags&PROBE_BIT_MASK) ? " (probed)" : "", (flags&REACH_BIT_MASK) ? "Reachable" : "Unreachable", prio, weight, m_prio, m_weight); offset += INET6_ADDRLEN; break; default: proto_tree_add_text(lisp_mapping_tree, tvb, 0, 2, "Unexpected AFI, cannot decode"); next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, lisp_mapping_tree); } 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 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static int dissect_lisp_mapping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lisp_tree, guint8 rec_cnt) { int i; gint offset = 0; gint mapver_offset = 0; guint32 ttl; guint8 loc_cnt; guint8 prefix_mask, flags, act; guint16 prefix_afi; guint32 prefix_v4; struct e_in6_addr prefix_v6; proto_item *tir; proto_tree *lisp_mapping_tree; tvbuff_t *next_tvb; const char *lisp_actions[] = { "No-Action", "Natively-Forward", "Send-Map-Request", "Drop", "Illegal action value" }; ttl = tvb_get_ntohl(tvb, offset); offset += 4; loc_cnt = tvb_get_guint8(tvb, offset); offset += 1; prefix_mask = tvb_get_guint8(tvb, offset); offset += 1; flags = tvb_get_guint8(tvb, offset); offset += 2; mapver_offset = offset; offset += 2; prefix_afi = tvb_get_ntohs(tvb, offset); offset += 2; act = flags & LISP_MAP_ACT; act >>= 5; if (act > 3) act = 4; switch (prefix_afi) { case AFNUM_INET: prefix_v4 = tvb_get_ipv4(tvb, offset); tir = proto_tree_add_text(lisp_tree, tvb, 0, 12 + INET_ADDRLEN, "EID prefix: %s/%d, TTL: %s, %sAuthoritative, %s", ip_to_str((guint8 *)&prefix_v4), prefix_mask, (ttl == 0xFFFFFFFF) ? "Unlimited" : g_strdup_printf("%d", ttl), (flags&LISP_MAP_AUTH) ? "" : "Not ", lisp_actions[act]); offset += INET_ADDRLEN; /* Update the INFO column if there is only one record */ if (rec_cnt == 1) col_append_fstr(pinfo->cinfo, COL_INFO, " for %s/%d", ip_to_str((guint8 *)&prefix_v4), prefix_mask); break; case AFNUM_INET6: tvb_get_ipv6(tvb, offset, &prefix_v6); tir = proto_tree_add_text(lisp_tree, tvb, 0, 12 + INET6_ADDRLEN, "EID prefix: %s/%d, TTL: %s, %sAuthoritative, %s", ip6_to_str(&prefix_v6), prefix_mask, (ttl == 0xFFFFFFFF) ? "Unlimited" : g_strdup_printf("%d", ttl), (flags&LISP_MAP_AUTH) ? "" : "Not ", lisp_actions[act]); offset += INET6_ADDRLEN; /* Update the INFO column if there is only one record */ if (rec_cnt == 1) col_append_fstr(pinfo->cinfo, COL_INFO, " for %s/%d", ip6_to_str(&prefix_v6), prefix_mask); break; default: proto_tree_add_text(lisp_tree, tvb, 0, 2, "Unexpected AFI, cannot decode"); next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, lisp_tree); return offset; } lisp_mapping_tree = proto_item_add_subtree(tir, ett_lisp_mapping); /* Reserved (4 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_res, tvb, mapver_offset, 2, ENC_BIG_ENDIAN); /* Map-Version Number (12 bits) */ proto_tree_add_item(lisp_mapping_tree, hf_lisp_mapping_ver, tvb, mapver_offset, 2, ENC_BIG_ENDIAN); /* 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); 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; gint offset = 0; gboolean mrep = FALSE; guint8 flags; guint8 itr_rec_cnt = 0; guint8 rec_cnt = 0; guint16 src_eid_afi; struct e_in6_addr e_in6_addr; tvbuff_t *next_tvb; /* Flags (6 bits)*/ flags = tvb_get_guint8(tvb, offset); mrep = flags & (MAP_REQ_FLAG_M >> 16); proto_tree_add_item(lisp_tree, hf_lisp_mreq_flags_auth, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mreq_flags_mrp, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mreq_flags_probe, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mreq_flags_smr, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mreq_flags_pitr, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(lisp_tree, hf_lisp_mreq_flags_smri, tvb, offset, 3, ENC_BIG_ENDIAN); /* 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_text(lisp_tree, tvb, offset, 0, "(Source EID not present)"); break; case AFNUM_INET: proto_tree_add_ipv4(lisp_tree, hf_lisp_mreq_srceid, tvb, offset, INET_ADDRLEN, tvb_get_ipv4(tvb, offset)); offset += INET_ADDRLEN; break; case AFNUM_INET6: tvb_get_ipv6(tvb, offset, &e_in6_addr); proto_tree_add_ipv6(lisp_tree, hf_lisp_mreq_srceidv6, tvb, offset, INET6_ADDRLEN, (guint8 *)&e_in6_addr); offset += INET6_ADDRLEN; break; default: proto_tree_add_text(lisp_tree, tvb, offset, 0, "Unexpected Source EID AFI, cannot decode"); next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, lisp_tree); return; } /* ITR records */ for(i=0; i < itr_rec_cnt+1; i++) { guint16 itr_afi; guint32 itr_rloc_v4; struct e_in6_addr itr_rloc_v6; proto_item *tir; proto_tree *lisp_itr_tree; itr_afi = tvb_get_ntohs(tvb, offset); switch (itr_afi) { case AFNUM_INET: itr_rloc_v4 = tvb_get_ipv4(tvb, offset + 2); tir = proto_tree_add_text(lisp_tree, tvb, offset, INET_ADDRLEN + 2, "ITR-RLOC %d: %s", i + 1, ip_to_str((guint8 *)&itr_rloc_v4)); lisp_itr_tree = proto_item_add_subtree(tir, ett_lisp_itr); proto_tree_add_text(lisp_itr_tree, tvb, offset, 2, "ITR-RLOC-AFI: %d", itr_afi); proto_tree_add_ipv4(lisp_itr_tree, hf_lisp_mreq_srcitr, tvb, offset + 2, INET_ADDRLEN, itr_rloc_v4); offset += INET_ADDRLEN + 2; break; case AFNUM_INET6: tvb_get_ipv6(tvb, offset + 2, &itr_rloc_v6); tir = proto_tree_add_text(lisp_tree, tvb, offset, INET6_ADDRLEN + 2, "ITR-RLOC %d: %s", i + 1, ip6_to_str(&itr_rloc_v6)); lisp_itr_tree = proto_item_add_subtree(tir, ett_lisp_itr); proto_tree_add_text(lisp_itr_tree, tvb, offset, 2, "ITR-RLOC-AFI: %d", itr_afi); proto_tree_add_ipv6(lisp_itr_tree, hf_lisp_mreq_srcitrv6, tvb, offset + 2, INET6_ADDRLEN, (guint8 *)&itr_rloc_v6); offset += INET6_ADDRLEN + 2; break; default: proto_tree_add_text(lisp_tree, tvb, offset, 2, "Unexpected ITR-RLOC-AFI, cannot decode"); next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, lisp_tree); return; } } /* Query records */ for(i=0; i < rec_cnt; i++) { guint8 reserved; guint8 prefix_mask; guint16 prefix_afi; guint32 prefix_v4; struct e_in6_addr prefix_v6; proto_item *tir; proto_tree *lisp_record_tree; reserved = tvb_get_guint8(tvb, offset); prefix_mask = tvb_get_guint8(tvb, offset + 1); prefix_afi = tvb_get_ntohs(tvb, offset + 2); switch (prefix_afi) { case AFNUM_INET: prefix_v4 = tvb_get_ipv4(tvb, offset + 4); tir = proto_tree_add_text(lisp_tree, tvb, offset, 4 + INET_ADDRLEN, "Record %d: %s/%d", i+1, ip_to_str((guint8 *)&prefix_v4), 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", ip_to_str((guint8 *)&prefix_v4), prefix_mask); lisp_record_tree = proto_item_add_subtree(tir, ett_lisp_record); proto_tree_add_text(lisp_record_tree, tvb, offset, 1, "Reserved bits: 0x%02X", reserved); proto_tree_add_text(lisp_record_tree, tvb, offset + 1, 1, "Prefix length: %d", prefix_mask); proto_tree_add_text(lisp_record_tree, tvb, offset + 2, 2, "Prefix AFI: %d", prefix_afi); proto_tree_add_text(lisp_record_tree, tvb, offset + 4, INET_ADDRLEN, "Prefix: %s", ip_to_str((guint8 *)&prefix_v4)); offset += 4 + INET_ADDRLEN; break; case AFNUM_INET6: tvb_get_ipv6(tvb, offset + 4, &prefix_v6); tir = proto_tree_add_text(lisp_tree, tvb, offset, 4 + INET6_ADDRLEN, "Record %d: %s/%d", i+1, ip6_to_str(&prefix_v6), 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", ip6_to_str(&prefix_v6), prefix_mask); lisp_record_tree = proto_item_add_subtree(tir, ett_lisp_record); proto_tree_add_text(lisp_record_tree, tvb, offset, 1, "Reserved bits: 0x%02X", reserved); proto_tree_add_text(lisp_record_tree, tvb, offset + 1, 1, "Prefix length: %d", prefix_mask); proto_tree_add_text(lisp_record_tree, tvb, offset + 2, 2, "Prefix AFI: %d", prefix_afi); proto_tree_add_text(lisp_record_tree, tvb, offset + 4, INET6_ADDRLEN, "Prefix: %s", ip6_to_str(&prefix_v6)); offset += 4 + INET6_ADDRLEN; break; default: proto_tree_add_text(lisp_tree, tvb, offset, 2, "Unexpected AFI, cannot decode"); next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, lisp_tree); return; } } /* If M bit is set, we also have a Map-Reply */ if (mrep) { int len = 0; tvbuff_t *rep_tvb; proto_item *tim; proto_tree *lisp_mr_tree; tim = proto_tree_add_text(lisp_tree, tvb, offset, -1, "Map-Reply record"); lisp_mr_tree = proto_item_add_subtree(tim, ett_lisp_mr); rep_tvb = tvb_new_subset_remaining(tvb, offset); len = dissect_lisp_mapping(rep_tvb, pinfo, lisp_mr_tree, 0); offset += len; } next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, 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| 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; guint8 rec_cnt = 0; tvbuff_t *next_tvb; /* Flags (2 bits) */ 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); /* 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++) { tvbuff_t *rec_tvb; int len = 0; rec_tvb = tvb_new_subset_remaining(tvb, offset); len = dissect_lisp_mapping(rec_tvb, pinfo, lisp_tree, rec_cnt); offset += len; } next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, 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| 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 | * +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ static void dissect_lisp_map_register(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; /* Flags (1 bit) */ proto_tree_add_item(lisp_tree, hf_lisp_mreg_flags_pmr, tvb, offset, 3, ENC_BIG_ENDIAN); /* Reserved bits (18 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_mreg_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_mreg_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_mreg_auth, tvb, offset, authlen, ENC_NA); offset += authlen; for(i=0; i < rec_cnt; i++) { tvbuff_t *rec_tvb; int len = 0; rec_tvb = tvb_new_subset_remaining(tvb, offset); len = dissect_lisp_mapping(rec_tvb, pinfo, lisp_tree, rec_cnt); offset += len; } next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, lisp_tree); } /* * 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 | 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; /* Reserved bits (20 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_mnot_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_mnot_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_mnot_auth, tvb, offset, authlen, ENC_NA); offset += authlen; for(i=0; i < rec_cnt; i++) { tvbuff_t *rec_tvb; int len = 0; rec_tvb = tvb_new_subset_remaining(tvb, offset); len = dissect_lisp_mapping(rec_tvb, pinfo, lisp_tree, rec_cnt); offset += len; } next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, lisp_tree); } /* * Dissector code for Encapsulated Control Message type packets * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Type=8 | 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 ip_ver; 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_dissector(data_handle, next_tvb, pinfo, tree); break; } encapsulated = FALSE; } /* * Main dissector code */ static int dissect_lisp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { 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 (0x%02x)")); } else { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, lisp_typevals, "Unknown (0x%02x)")); } 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); break; case LISP_MAP_NOTIFY: dissect_lisp_map_notify(tvb, pinfo, lisp_tree); break; case LISP_ECM: encapsulated = TRUE; dissect_lisp_ecm(tvb, pinfo, tree, lisp_tree); break; default: call_dissector(data_handle, tvb, pinfo, tree); break; } /* Return the amount of data this dissector was able to dissect */ return tvb_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_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, NULL, 0x0, "Source EID Address Family Indicator", HFILL }}, { &hf_lisp_mreq_srceid, { "Source EID", "lisp.mreq.srceid", FT_IPv4, BASE_NONE, NULL, 0x0, "Source EID Address", HFILL }}, { &hf_lisp_mreq_srceidv6, { "Source EID", "lisp.mreq.srceidv6", FT_IPv6, BASE_NONE, NULL, 0x0, "Source EID Address", HFILL }}, { &hf_lisp_mreq_srcitr, { "ITR-RLOC Address", "lisp.mreq.srcitr", FT_IPv4, BASE_NONE, NULL, 0x0, "Originating ITR RLOC Address", HFILL }}, { &hf_lisp_mreq_srcitrv6, { "ITR-RLOC Address", "lisp.mreq.srcitrv6", FT_IPv6, BASE_NONE, NULL, 0x0, "Originating ITR RLOC Address", HFILL }}, { &hf_lisp_mrep_flags, { "Flags", "lisp.mrep.flags", FT_UINT8, BASE_HEX, NULL, 0x06, 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_res, { "Reserved bits", "lisp.mrep.res", FT_UINT24, BASE_HEX, NULL, MAP_REP_RESERVED, "Must be zero", HFILL }}, { &hf_lisp_mreg_flags, { "Flags", "lisp.mreg.flags", FT_UINT8, BASE_HEX, NULL, 0x08, NULL, 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_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_mreg_keyid, { "Key ID", "lisp.mreg.keyid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreg_authlen, { "Authentication Data Length", "lisp.mreg.authlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mreg_auth, { "Authentication Data", "lisp.mreg.auth", FT_BYTES, BASE_NONE, NULL, 0x0, 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_mnot_keyid, { "Key ID", "lisp.mnot.keyid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mnot_authlen, { "Authentication Data Length", "lisp.mnot.authlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mnot_auth, { "Authentication Data", "lisp.mnot.auth", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_lisp_mapping_res, { "Reserved", "lisp.mapping.res", 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_ecm_res, { "Reserved bits", "lisp.ecm_res", FT_UINT32, BASE_HEX, NULL, 0x0FFFFFFF, NULL, HFILL }}, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_lisp, &ett_lisp_mr, &ett_lisp_mapping, &ett_lisp_itr, &ett_lisp_record }; /* 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)); } /* * 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_handle_t lisp_handle; lisp_handle = new_create_dissector_handle(dissect_lisp, proto_lisp); dissector_add_uint("udp.port", LISP_CONTROL_PORT, lisp_handle); ipv4_handle = find_dissector("ip"); ipv6_handle = find_dissector("ipv6"); data_handle = find_dissector("data"); } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=4 expandtab: * :indentSize=4:tabSize=4:noTabs=true: */