static void dissect_ripng(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; proto_tree *ripng_tree = NULL, *rte_tree = NULL; proto_item *ti, *rte_ti; col_set_str(pinfo->cinfo, COL_PROTOCOL, "RIPng"); if (check_col(pinfo->cinfo, COL_INFO)) { col_clear(pinfo->cinfo, COL_INFO); col_add_fstr(pinfo->cinfo, COL_INFO," Command %s, Version %u", val_to_str(tvb_get_guint8(tvb, offset), cmdvals, "Unknown (%u)"), tvb_get_guint8(tvb, offset +1)); } if (tree) { ti = proto_tree_add_item(tree, proto_ripng, tvb, offset, -1, FALSE); ripng_tree = proto_item_add_subtree(ti, ett_ripng); /* Command */ proto_tree_add_item(ripng_tree, hf_ripng_cmd, tvb, offset, 1, FALSE); offset += 1; /* Version */ proto_tree_add_item(ripng_tree, hf_ripng_version, tvb, offset, 1, FALSE); offset += 1; /* Reserved */ proto_tree_add_item(ripng_tree, hf_ripng_reserved, tvb, offset, 2, FALSE); offset += 2; /* Route Table Entry */ while (tvb_reported_length_remaining(tvb, offset) > 0) { rte_ti = proto_tree_add_item(ripng_tree, hf_ripng_rte, tvb, offset, 16 + 2 + 1 + 1, FALSE); rte_tree = proto_item_add_subtree(rte_ti, ett_ripng_rte); /* IPv6 Prefix */ proto_tree_add_item(rte_tree, hf_ripng_rte_ipv6_prefix, tvb, offset, 16, FALSE); proto_item_append_text(rte_ti, ": IPv6 Prefix: %s", tvb_ip6_to_str(tvb, offset)); offset += 16; /* Route Tag */ proto_tree_add_item(rte_tree, hf_ripng_rte_route_tag, tvb, offset, 2, FALSE); offset += 2; /* Prefix Length */ proto_tree_add_item(rte_tree, hf_ripng_rte_prefix_length, tvb, offset, 1, FALSE); proto_item_append_text(rte_ti, "/%u", tvb_get_guint8(tvb, offset)); offset += 1; /* Metric */ proto_tree_add_item(rte_tree, hf_ripng_rte_metric, tvb, offset, 1, FALSE); proto_item_append_text(rte_ti, " Metric: %u", tvb_get_guint8(tvb, offset)); offset += 1; } } }
static proto_item * decode_ip_element(nsip_ip_element_info_t *element, build_info_t *bi, proto_tree * element_tree) { guint16 udp_port; proto_item *tf; proto_tree *field_tree; field_tree = proto_tree_add_subtree(element_tree, bi->tvb, bi->offset, element->total_length, ett_nsip_ip_element, &tf, "IP Element"); if (bi->nsip_tree) { /* IP address */ switch (element->version) { case NSIP_IP_VERSION_4: proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv4, bi->tvb, bi->offset, element->address_length, ENC_BIG_ENDIAN); proto_item_append_text(tf, ": IP address: %s", tvb_ip_to_str(bi->tvb, bi->offset)); break; case NSIP_IP_VERSION_6: proto_tree_add_item(field_tree, hf_nsip_ip_address_ipv6, bi->tvb, bi->offset, element->address_length, ENC_NA); proto_item_append_text(tf, ": IP address: %s", tvb_ip6_to_str(bi->tvb, bi->offset)); break; default: ; } } bi->offset += element->address_length; if (bi->nsip_tree) { /* UDP port value */ udp_port = tvb_get_ntohs(bi->tvb, bi->offset); proto_tree_add_item(field_tree, hf_nsip_ip_element_udp_port, bi->tvb, bi->offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(tf, ", UDP Port: %u", udp_port); } bi->offset += 2; if (bi->nsip_tree) { /* Signalling weight */ proto_tree_add_item(field_tree, hf_nsip_ip_element_signalling_weight, bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN); } bi->offset++; if (bi->nsip_tree) { /* Data weight */ proto_tree_add_item(field_tree, hf_nsip_ip_element_data_weight, bi->tvb, bi->offset, 1, ENC_BIG_ENDIAN); } bi->offset++; return tf; }
static void dissect_sap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; int sap_version, is_ipv6, is_del, is_enc, is_comp, addr_len; guint8 vers_flags; guint8 auth_len; guint16 tmp1; guint8 auth_flags; tvbuff_t *next_tvb; proto_item *si, *sif; proto_tree *sap_tree, *sap_flags_tree; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAP"); col_clear(pinfo->cinfo, COL_INFO); vers_flags = tvb_get_guint8(tvb, offset); is_ipv6 = vers_flags&MCAST_SAP_BIT_A; is_del = vers_flags&MCAST_SAP_BIT_T; is_enc = vers_flags&MCAST_SAP_BIT_E; is_comp = vers_flags&MCAST_SAP_BIT_C; sap_version = (vers_flags&MCAST_SAP_VERSION_MASK)>>MCAST_SAP_VERSION_SHIFT; addr_len = (is_ipv6) ? sizeof(struct e_in6_addr) : 4; if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%u)", (is_del) ? "Deletion" : "Announcement", sap_version); } if (tree) { si = proto_tree_add_item(tree, proto_sap, tvb, offset, -1, ENC_NA); sap_tree = proto_item_add_subtree(si, ett_sap); sif = proto_tree_add_uint(sap_tree, hf_sap_flags, tvb, offset, 1, vers_flags); sap_flags_tree = proto_item_add_subtree(sif, ett_sap_flags); proto_tree_add_uint(sap_flags_tree, hf_sap_flags_v, tvb, offset, 1, vers_flags); proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_a, tvb, offset, 1, vers_flags); proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_r, tvb, offset, 1, vers_flags); proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_t, tvb, offset, 1, vers_flags); proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_e, tvb, offset, 1, vers_flags); proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_c, tvb, offset, 1, vers_flags); offset++; auth_len = tvb_get_guint8(tvb, offset); proto_tree_add_text(sap_tree, tvb, offset, 1, "Authentication Length: %u", auth_len); offset++; tmp1 = tvb_get_ntohs(tvb, offset); proto_tree_add_text(sap_tree, tvb, offset, 2, "Message Identifier Hash: 0x%x", tmp1); offset +=2; proto_tree_add_text(sap_tree, tvb, offset, addr_len, "Originating Source: %s", (is_ipv6) ? tvb_ip6_to_str(tvb, offset) : tvb_ip_to_str(tvb, offset)); offset += addr_len; /* Authentication data lives in its own subtree */ if (auth_len > 0) { guint32 auth_data_len; proto_item *sdi, *sai; proto_tree *sa_tree, *saf_tree; int has_pad; guint8 pad_len = 0; auth_data_len = auth_len * sizeof(guint32); sdi = proto_tree_add_item(sap_tree, hf_auth_data, tvb, offset, auth_data_len, ENC_NA); sa_tree = proto_item_add_subtree(sdi, ett_sap_auth); auth_flags = tvb_get_guint8(tvb, offset); sai = proto_tree_add_uint(sa_tree, hf_auth_flags, tvb, offset, 1, auth_flags); saf_tree = proto_item_add_subtree(sai, ett_sap_authf); proto_tree_add_uint(saf_tree, hf_auth_flags_v, tvb, offset, 1, auth_flags); proto_tree_add_boolean(saf_tree, hf_auth_flags_p, tvb, offset, 1, auth_flags); proto_tree_add_uint(saf_tree, hf_auth_flags_t, tvb, offset, 1, auth_flags); has_pad = auth_flags&MCAST_SAP_AUTH_BIT_P; if (has_pad) pad_len = tvb_get_guint8(tvb, offset+auth_data_len-1); if ((int) auth_data_len - pad_len - 1 < 0) { proto_tree_add_text(sa_tree, tvb, 0, 0, "Bogus authentication length (%d) or pad length (%d)", auth_len, pad_len); return; } proto_tree_add_text(sa_tree, tvb, offset+1, auth_data_len-pad_len-1, "Authentication subheader: (%u byte%s)", auth_data_len-1, plurality(auth_data_len-1, "", "s")); if (has_pad) { proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-pad_len, pad_len, "Authentication data padding: (%u byte%s)", pad_len, plurality(pad_len, "", "s")); proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-1, 1, "Authentication data pad count: %u byte%s", pad_len, plurality(pad_len, "", "s")); } offset += auth_data_len; } if (is_enc || is_comp) { const char *mangle; if (is_enc && is_comp) mangle = "compressed and encrypted"; else if (is_enc) mangle = "encrypted"; else mangle = "compressed"; proto_tree_add_text(sap_tree, tvb, offset, -1, "The rest of the packet is %s", mangle); return; } /* Do we have the optional payload type aka. MIME content specifier */ if (tvb_strneql(tvb, offset, "v=", strlen("v="))) { gint remaining_len; guint32 pt_len; int pt_string_len; remaining_len = tvb_length_remaining(tvb, offset); if (remaining_len == 0) { /* * "tvb_strneql()" failed because there was no * data left in the packet. * * Set the remaining length to 1, so that * we throw the appropriate exception in * "tvb_get_ptr()", rather than displaying * the payload type. */ remaining_len = 1; } pt_string_len = tvb_strnlen(tvb, offset, remaining_len); if (pt_string_len == -1) { /* * We didn't find a terminating '\0'; run to the * end of the buffer. */ pt_string_len = remaining_len; pt_len = pt_string_len; } else { /* * Include the '\0' in the total item length. */ pt_len = pt_string_len + 1; } proto_tree_add_text(sap_tree, tvb, offset, pt_len, "Payload type: %.*s", pt_string_len, tvb_get_ephemeral_string(tvb, offset, pt_string_len)); offset += pt_len; } } /* Done with SAP */ next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(sdp_handle, next_tvb, pinfo, tree); return; }
/* * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03 * (when PIM is run over IPv6, the rules for computing the PIM checksum * from the draft in question, not from RFC 2362, should be used). */ static void dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 pim_typever; guint length, pim_length; guint16 pim_cksum, computed_cksum; vec_t cksum_vec[4]; guint32 phdr[2]; const char *typestr; proto_tree *pim_tree = NULL; proto_item *ti; proto_tree *pimopt_tree = NULL; proto_item *tiopt; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM"); col_clear(pinfo->cinfo, COL_INFO); pim_typever = tvb_get_guint8(tvb, 0); switch (PIM_VER(pim_typever)) { case 2: typestr = val_to_str(PIM_TYPE(pim_typever), type2vals, "Unknown (%u)"); break; case 1: /* PIMv1 - we should never see this */ default: typestr = "Unknown"; break; } if (check_col(pinfo->cinfo, COL_PROTOCOL)) { col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d", PIM_VER(pim_typever)); } if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, typestr); ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, ENC_NA); pim_tree = proto_item_add_subtree(ti, ett_pim); proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, ENC_NA); pim_cksum = tvb_get_ntohs(tvb, offset + 2); length = tvb_length(tvb); if (PIM_VER(pim_typever) == 2) { /* * Well, it's PIM v2, so we can check whether this is a Register * message, and thus can figure out how much to checksum and * whether to make the columns read-only. */ if (PIM_TYPE(pim_typever) == 1) { /* * Register message - the PIM header is 8 bytes long. * Also set the columns non-writable. Otherwise the IPv4 or * IPv6 dissector for the encapsulated packet that caused * this register will overwrite the PIM info in the columns. */ pim_length = 8; col_set_writable(pinfo->cinfo, FALSE); } else { /* * Other message - checksum the entire packet. */ pim_length = tvb_reported_length(tvb); } } else { /* * We don't know what type of message this is, so say that * the length is 0, to force it not to be checksummed. */ pim_length = 0; } if (!pinfo->fragmented && length >= pim_length) { /* * The packet isn't part of a fragmented datagram and isn't * truncated, so we can checksum it. */ switch (pinfo->src.type) { case AT_IPv4: cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[0].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 1); break; case AT_IPv6: /* Set up the fields of the pseudo-header. */ cksum_vec[0].ptr = pinfo->src.data; cksum_vec[0].len = pinfo->src.len; cksum_vec[1].ptr = pinfo->dst.data; cksum_vec[1].len = pinfo->dst.len; cksum_vec[2].ptr = (const guint8 *)&phdr; phdr[0] = g_htonl(pim_length); phdr[1] = g_htonl(IP_PROTO_PIM); cksum_vec[2].len = 8; cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[3].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 4); break; default: /* PIM is available for IPv4 and IPv6 right now */ computed_cksum = 0; /* squelch GCC complaints */ DISSECTOR_ASSERT_NOT_REACHED(); break; } if (computed_cksum == 0) { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum, "Checksum: 0x%04x [correct]", pim_cksum); } else { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum)); } } else { proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb, offset + 2, 2, pim_cksum); } offset += 4; if (tvb_reported_length_remaining(tvb, offset) > 0) { tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options"); pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts); } else goto done; if (PIM_VER(pim_typever) != 2) goto done; /* version 2 decoder */ switch (PIM_TYPE(pim_typever)) { case 0: /*hello*/ { int opt_count = 0; while (tvb_reported_length_remaining(tvb, offset) >= 2) { guint16 hello_opt, opt_len; guint16 opt_value; proto_item *opt_item; proto_tree *opt_tree; opt_count++; hello_opt = tvb_get_ntohs(tvb, offset); opt_len = tvb_get_ntohs(tvb, offset + 2); opt_item = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len, "Option %u: %s", hello_opt, val_to_str(hello_opt, pim_opt_vals, "Unknown: %u")); opt_tree = proto_item_add_subtree(opt_item, ett_pim_opt); proto_tree_add_item(opt_tree, hf_pim_optiontype, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, ENC_BIG_ENDIAN); switch(hello_opt) { case 1: /* Hello Hold Time Option */ opt_value = tvb_get_ntohs(tvb, offset + 4); proto_tree_add_uint_format(opt_tree, hf_pim_holdtime, tvb, offset + 4, opt_len, opt_value, "Holdtime: %us %s", opt_value, opt_value == 0 ? "(goodbye)" : opt_value == 0xffff ? "(infinity)": ""); proto_item_append_text(opt_item, ": %us %s", opt_value, opt_value == 0 ? "(goodbye)" : opt_value == 0xffff ? "(infinity)": ""); break; case 2: /* LAN Prune Delay Option */ proto_tree_add_item(opt_tree, hf_pim_t, tvb, offset + 4, 1, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": T = %u, Propagation Delay = %ums, Override Interval = %ums", tvb_get_guint8(tvb, offset + 4) & 0x80 ? 1 : 0, tvb_get_ntohs(tvb, offset + 4) & 0x7fff, tvb_get_ntohs(tvb, offset + 6)); break; case 19: /* DR priority */ proto_tree_add_item(opt_tree, hf_pim_dr_priority, tvb, offset + 4, 4, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4)); break; case 20: /* Generation ID */ proto_tree_add_item(opt_tree, hf_pim_generation_id, tvb, offset + 4, 4, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4)); break; case 21: /* State Refresh Capable Option */ proto_tree_add_item(opt_tree, hf_pim_state_refresh_version, tvb, offset + 4, 1, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, ENC_BIG_ENDIAN); proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, ENC_BIG_ENDIAN); proto_item_append_text(opt_item, ": Version = %u, Interval = %us", tvb_get_guint8(tvb, offset + 4), tvb_get_guint8(tvb, offset + 5)); break; case 24: /* address list */ case 65001: /* address list (old implementations) */ { int i; proto_tree *sub_tree = NULL; proto_item *addrlist_option; addrlist_option = proto_tree_add_text(opt_tree, tvb, offset, 4 + opt_len, "%sAddress List (%u)", hello_opt == 65001 ? "old " : "", hello_opt); sub_tree = proto_item_add_subtree(addrlist_option, ett_pim_opt); for (i = offset + 4; i < offset + 4 + opt_len; ) { int advance; const char *s; s = dissect_pim_addr(tvb, i, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(sub_tree, tvb, offset, advance, "Address: %s", s); i += advance; } break; } default: if (opt_len) proto_tree_add_item(opt_tree, hf_pim_optionvalue, tvb, offset + 4, opt_len, ENC_NA); break; } offset += 4 + opt_len; } proto_item_append_text(tiopt, ": %u", opt_count); break; } case 1: /* register */ { guint32 flags; guint8 v_hl; tvbuff_t *next_tvb; proto_tree *flag_tree = NULL; proto_item *tiflag; flags = tvb_get_ntohl(tvb, offset); tiflag = proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Flags: 0x%08x", flags); flag_tree = proto_item_add_subtree(tiflag, ett_pim); proto_tree_add_text(flag_tree, tvb, offset, 1, "%s", decode_boolean_bitfield(flags, 0x80000000, 32, "Border", "Not border")); proto_tree_add_text(flag_tree, tvb, offset, 1, "%s", decode_boolean_bitfield(flags, 0x40000000, 32, "Null-Register", "Not Null-Register")); offset += 4; /* * The rest of the packet is a multicast data packet. */ next_tvb = tvb_new_subset_remaining(tvb, offset); /* * It's an IP packet - determine whether it's IPv4 or IPv6. */ v_hl = tvb_get_guint8(tvb, offset); switch((v_hl & 0xf0) >> 4) { case 0: /* Null-Register dummy header. * Has the same address family as the encapsulating PIM packet, * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet. */ if (pinfo->src.type == AT_IPv4) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv4 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4, "Source: %s", tvb_ip_to_str(tvb, offset + 12)); proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4, "Group: %s", tvb_ip_to_str(tvb, offset + 16)); } else if (pinfo->src.type == AT_IPv6) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv6 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 8, 16, "Source: %s", tvb_ip6_to_str(tvb, offset + 8)); proto_tree_add_text(pimopt_tree, tvb, offset + 8 + 16, 16, "Group: %s", tvb_ip6_to_str(tvb, offset + 8 + 16)); } else proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Dummy header for an unknown protocol"); break; case 4: /* IPv4 */ #if 0 call_dissector(ip_handle, next_tvb, pinfo, tree); #else call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree); #endif break; case 6: /* IPv6 */ #if 0 call_dissector(ipv6_handle, next_tvb, pinfo, tree); #else call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree); #endif break; default: proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Unknown IP version %d", (v_hl & 0xf0) >> 4); break; } break; } case 2: /* register-stop */ { int advance; const char *s; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); break; } case 3: /* join/prune */ case 6: /* graft */ case 7: /* graft-ack */ { int advance; int off; const char *s; int ngroup, i, njoin, nprune, j; guint16 holdtime; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree *subtree = NULL; proto_item *tisub; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Upstream-neighbor: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_res_bytes, tvb, offset, 1, ENC_NA); offset += 1; /* skip reserved field */ ngroup = tvb_get_guint8(tvb, offset); proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; for (i = 0; i < ngroup; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak3; tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += advance; njoin = tvb_get_ntohs(tvb, offset); nprune = tvb_get_ntohs(tvb, offset + 2); tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb, offset, 2, ENC_BIG_ENDIAN); subtree = proto_item_add_subtree(tisub, ett_pim); off = offset + 4; for (j = 0; j < njoin; j++) { s = dissect_pim_addr(tvb, off, pimv2_source, &advance); if (s == NULL) goto breakbreak3; proto_tree_add_text(subtree, tvb, off, advance, "IP address: %s", s); off += advance; } tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb, offset + 2, 2, ENC_BIG_ENDIAN); subtree = proto_item_add_subtree(tisub, ett_pim); for (j = 0; j < nprune; j++) { s = dissect_pim_addr(tvb, off, pimv2_source, &advance); if (s == NULL) goto breakbreak3; proto_tree_add_text(subtree, tvb, off, advance, "IP address: %s", s); off += advance; } offset = off; } breakbreak3: break; } case 4: /* bootstrap */ { const char *s; int advance; int i, j; int frpcnt; guint16 holdtime; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree_add_text(pimopt_tree, tvb, offset, 2, "Fragment tag: 0x%04x", tvb_get_ntohs(tvb, offset)); offset += 2; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Hash mask len: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "BSR priority: %u", tvb_get_guint8(tvb, offset)); offset += 1; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "BSR: %s", s); offset += advance; for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak4; tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += advance; proto_tree_add_text(grouptree, tvb, offset, 1, "RP count: %u", tvb_get_guint8(tvb, offset)); offset += 1; frpcnt = tvb_get_guint8(tvb, offset); proto_tree_add_text(grouptree, tvb, offset, 1, "FRP count: %u", frpcnt); offset += 3; for (j = 0; j < frpcnt; j++) { s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) goto breakbreak4; proto_tree_add_text(grouptree, tvb, offset, advance, "RP %d: %s", j, s); offset += advance; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(grouptree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; proto_tree_add_text(grouptree, tvb, offset, 1, "Priority: %u", tvb_get_guint8(tvb, offset)); offset += 2; /* also skips reserved field */ } } breakbreak4: break; } case 5: /* assert */ { const char *s; int advance; guint32 pref; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; } case 8: /* Candidate-RP-Advertisement */ { const char *s; int advance; int pfxcnt; guint16 holdtime; int i; pfxcnt = tvb_get_guint8(tvb, offset); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prefix-count: %u", pfxcnt); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Priority: %u", tvb_get_guint8(tvb, offset)); offset += 1; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "RP: %s", s); offset += advance; for (i = 0; i < pfxcnt; i++) { s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) goto breakbreak8; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group %d: %s", i, s); offset += advance; } breakbreak8: break; } case 9: /* State-Refresh */ { const char *s; int advance; guint32 pref; s = dissect_pim_addr(tvb, offset, pimv2_group, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s); offset += advance; s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance); if (s == NULL) break; proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Originator: %s", s); offset += advance; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Masklen: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "TTL: %u", tvb_get_guint8(tvb, offset)); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune indicator %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8, "set", "clear")); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune now %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x40, 8, "set", "clear")); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Assert override %s", decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x20, 8, "set", "clear")); offset += 1; proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Interval: %u", tvb_get_guint8(tvb, offset)); offset += 1; break; } default: break; } done:; }
static const char * dissect_pim_addr(tvbuff_t *tvb, int offset, enum pimv2_addrtype at, int *advance) { emem_strbuf_t *strbuf; guint8 af; guint8 et; guint8 flags; guint8 mask_len; int len = 0; af = tvb_get_guint8(tvb, offset); if (af != AFNUM_INET && af != AFNUM_INET6) { /* * We don't handle the other formats, and addresses don't include * a length field, so we can't even show them as raw bytes. */ return NULL; } et = tvb_get_guint8(tvb, offset + 1); if (et != 0) { /* * The only defined encoding type is 0, for the native encoding; * again, as addresses don't include a length field, we can't * even show addresses with a different encoding type as raw * bytes. */ return NULL; } strbuf = ep_strbuf_new_label(NULL); switch (at) { case pimv2_unicast: switch (af) { case AFNUM_INET: len = 4; ep_strbuf_printf(strbuf, "%s", tvb_ip_to_str(tvb, offset + 2)); break; case AFNUM_INET6: len = 16; ep_strbuf_printf(strbuf, "%s", tvb_ip6_to_str(tvb, offset + 2)); break; } if (advance) *advance = 2 + len; break; case pimv2_group: mask_len = tvb_get_guint8(tvb, offset + 3); switch (af) { case AFNUM_INET: len = 4; ep_strbuf_printf(strbuf, "%s/%u", tvb_ip_to_str(tvb, offset + 4), mask_len); break; case AFNUM_INET6: len = 16; ep_strbuf_printf(strbuf, "%s/%u", tvb_ip6_to_str(tvb, offset + 4), mask_len); break; } if (advance) *advance = 4 + len; break; case pimv2_source: flags = tvb_get_guint8(tvb, offset + 2); mask_len = tvb_get_guint8(tvb, offset + 3); switch (af) { case AFNUM_INET: len = 4; ep_strbuf_printf(strbuf, "%s/%u", tvb_ip_to_str(tvb, offset + 4), mask_len); break; case AFNUM_INET6: len = 16; ep_strbuf_printf(strbuf, "%s/%u", tvb_ip6_to_str(tvb, offset + 4), mask_len); break; } if (flags) { ep_strbuf_append_printf(strbuf, " (%s%s%s)", flags & 0x04 ? "S" : "", flags & 0x02 ? "W" : "", flags & 0x01 ? "R" : ""); } if (advance) *advance = 4 + len; break; default: return NULL; } return strbuf->str; }
/* This function is only called from the IGMP dissector */ int dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) { guint8 pim_type; guint8 pim_ver; guint length, pim_length; guint16 pim_cksum, computed_cksum; vec_t cksum_vec[1]; proto_tree *pim_tree = NULL; proto_item *ti; proto_tree *pimopt_tree = NULL; proto_item *tiopt; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_pim))) { /* * We are not enabled; skip entire packet to be nice to the * IGMP layer (so clicking on IGMP will display the data). */ return offset+tvb_length_remaining(tvb, offset); } col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIMv1"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, ENC_NA); pim_tree = proto_item_add_subtree(ti, ett_pim); /* Put IGMP type, 0x14, into the tree */ proto_tree_add_text(pim_tree, tvb, offset, 1, "Type: PIM (0x14)"); offset += 1; pim_type = tvb_get_guint8(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pim_type, type1vals, "Unknown (%u)")); proto_tree_add_uint(pim_tree, hf_pim_code, tvb, offset, 1, pim_type); offset += 1; pim_cksum = tvb_get_ntohs(tvb, offset); pim_ver = PIM_VER(tvb_get_guint8(tvb, offset + 2)); if (pim_ver != 1) { /* * Not PIMv1 - what gives? */ proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum); offset += 2; proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN); return offset+tvb_length_remaining(tvb, offset); } /* * Well, it's PIM v1, so we can check whether this is a * Register message, and thus can figure out how much to * checksum and whether to make the columns read-only. */ length = tvb_length(tvb); if (pim_type == 1) { /* * Register message - the PIM header is 8 bytes long. * Also set the columns non-writable. Otherwise the IPv4 or * IPv6 dissector for the encapsulated packet that caused * this register will overwrite the PIM info in the columns. */ pim_length = 8; col_set_writable(pinfo->cinfo, FALSE); } else { /* * Other message - checksum the entire packet. */ pim_length = tvb_reported_length(tvb); } if (!pinfo->fragmented && length >= pim_length) { /* * The packet isn't part of a fragmented datagram and isn't * truncated, so we can checksum it. */ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length); cksum_vec[0].len = pim_length; computed_cksum = in_cksum(&cksum_vec[0], 1); if (computed_cksum == 0) { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum, "Checksum: 0x%04x [correct]", pim_cksum); } else { proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]", pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum)); } } else { proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb, offset, 2, pim_cksum); } offset += 2; proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; offset += 3; /* skip reserved stuff */ if (tvb_reported_length_remaining(tvb, offset) > 0) { tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options"); pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts); } else goto done; /* version 1 decoder */ switch (pim_type) { case 0: /* query */ { guint16 holdtime; proto_tree_add_item(pimopt_tree, hf_pim_mode, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 2; holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; break; } case 1: /* register */ { guint8 v_hl; tvbuff_t *next_tvb; /* * The rest of the packet is a multicast data packet. */ next_tvb = tvb_new_subset_remaining(tvb, offset); /* * It's an IP packet - determine whether it's IPv4 or IPv6. */ v_hl = tvb_get_guint8(tvb, offset); switch((v_hl & 0xf0) >> 4) { case 0: /* Null-Register dummy header. * Has the same address family as the encapsulating PIM packet, * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet. */ if (pinfo->src.type == AT_IPv4) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv4 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4, "Source: %s", tvb_ip_to_str(tvb, offset + 12)); proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4, "Group: %s", tvb_ip_to_str(tvb, offset + 16)); } else if (pinfo->src.type == AT_IPv6) { proto_tree_add_text(pimopt_tree, tvb, offset, -1, "IPv6 dummy header"); proto_tree_add_text(pimopt_tree, tvb, offset + 8, 16, "Source: %s", tvb_ip6_to_str(tvb, offset + 8)); proto_tree_add_text(pimopt_tree, tvb, offset + 8 + 16, 16, "Group: %s", tvb_ip6_to_str(tvb, offset + 8)); } else proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Dummy header for an unknown protocol"); break; case 4: /* IPv4 */ #if 0 call_dissector(ip_handle, next_tvb, pinfo, tree); #else call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree); #endif break; case 6: /* IPv6 */ #if 0 call_dissector(ipv6_handle, next_tvb, pinfo, tree); #else call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree); #endif break; default: proto_tree_add_text(pimopt_tree, tvb, offset, -1, "Unknown IP version %d", (v_hl & 0xf0) >> 4); break; } break; } case 2: /* register-stop */ { proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Source: %s", tvb_ip_to_str(tvb, offset)); offset += 4; break; } case 3: /* join/prune */ case 6: /* graft */ case 7: /* graft-ack */ { int off; const char *s; int ngroup, i, njoin, nprune, j; guint16 holdtime; guint8 mask_len; guint8 adr_len; proto_tree *grouptree = NULL; proto_item *tigroup; proto_tree *subtree = NULL; proto_item *tisub; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Upstream-neighbor: %s", tvb_ip_to_str(tvb, offset)); offset += 4; offset += 2; /* skip reserved stuff */ holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; offset += 1; /* skip reserved stuff */ mask_len = tvb_get_guint8(tvb, offset); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Mask length: %u", mask_len); offset += 1; adr_len = tvb_get_guint8(tvb, offset); proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Address length: %u", adr_len); offset += 1; ngroup = tvb_get_guint8(tvb, offset); proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; for (i = 0; i < ngroup; i++) { /* * XXX - does the group address have the length "adr_len" * and the group mask the length "mask_len"? */ tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group %d: %s", i, tvb_ip_to_str(tvb, offset)); grouptree = proto_item_add_subtree(tigroup, ett_pim); offset += 4; proto_tree_add_text(grouptree, tvb, offset, 4, "Group %d Mask: %s", i, tvb_ip_to_str(tvb, offset)); offset += 4; njoin = tvb_get_ntohs(tvb, offset); nprune = tvb_get_ntohs(tvb, offset + 2); tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb, offset, 2, ENC_BIG_ENDIAN); subtree = proto_item_add_subtree(tisub, ett_pim); off = offset + 4; for (j = 0; j < njoin; j++) { s = dissect_pimv1_addr(tvb, off); proto_tree_add_text(subtree, tvb, off, 6, "IP address: %s", s); off += 6; } tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb, offset + 2, 2, ENC_BIG_ENDIAN); subtree = proto_item_add_subtree(tisub, ett_pim); for (j = 0; j < nprune; j++) { s = dissect_pimv1_addr(tvb, off); proto_tree_add_text(subtree, tvb, off, 6, "IP address: %s", s); off += 6; } offset = off; } break; } case 4: /* rp-reachability */ { guint16 holdtime; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Address: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Mask: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "RP Address: %s", tvb_ip_to_str(tvb, offset)); offset += 4; offset += 2; /* skip reserved stuff */ holdtime = tvb_get_ntohs(tvb, offset); proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, holdtime, "Holdtime: %us %s", holdtime, holdtime == 0xffff ? "(infinity)": ""); offset += 2; break; } case 5: /* assert */ { guint32 pref; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Address: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Group Mask: %s", tvb_ip_to_str(tvb, offset)); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN); pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff; proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb, offset, 4, pref, "Metric Preference: %u", pref); offset += 4; proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; } default: break; } done:; return offset+tvb_length_remaining(tvb, offset); }
static void dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { proto_tree_add_item(parameter_tree, hf_parameter_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, ENC_NA); proto_item_append_text(parameter_item, " (%s)", tvb_ip6_to_str(parameter_tvb, IPV6_ADDRESS_OFFSET)); }
static int dissect_lisp_tcp_membership_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *message_tree, guint offset, guint16 type, guint16 data_len, proto_item *tim) { guint32 iid, sid, rid; guint8 err; guint64 siteid; guint16 afi; /* EID AFI (2 bytes) */ proto_tree_add_item(message_tree, hf_lisp_tcp_message_eid_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; data_len -= 2; /* Instance ID (4 bytes) */ iid = tvb_get_ntohl(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_iid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; proto_item_append_text(tim, ", IID: %u", iid); switch (type) { case MEMBERSHIP_BASE + 1: case MEMBERSHIP_BASE + 2: /* Subscribe ID (4 bytes) */ sid = tvb_get_ntohl(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_sid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; col_append_fstr(pinfo->cinfo, COL_INFO, ", Sub ID: %u", sid); proto_item_append_text(tim, ", Sub ID: %u", sid); if (type == MEMBERSHIP_BASE + 2) { /* Error code (1 byte) */ err = tvb_get_guint8(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_err, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; data_len -= 1; proto_item_append_text(tim, ", Error code: %s", val_to_str(err, lisp_tcp_membership_subscribe_errors, "Unknown error code (%u)")); } break; case MEMBERSHIP_BASE + 4: case MEMBERSHIP_BASE + 5: /* Site ID (8 bytes) */ siteid = tvb_get_ntoh64(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_site_id, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; data_len -= 8; proto_item_append_text(tim, ", Site-ID: %"G_GINT64_MODIFIER"u", siteid); /* RLOC AFI (2 bytes) */ afi = tvb_get_ntohs(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_rloc_afi, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; data_len -= 2; switch (afi) { case AFNUM_INET: proto_tree_add_item(message_tree, hf_lisp_tcp_message_rloc_ipv4, tvb, offset, INET_ADDRLEN, ENC_NA); proto_item_append_text(tim, ", RLOC: %s", tvb_ip_to_str(tvb, offset)); col_append_fstr(pinfo->cinfo, COL_INFO, " [%u] %s", iid, tvb_ip_to_str(tvb, offset)); offset += INET_ADDRLEN; data_len -= INET_ADDRLEN; break; case AFNUM_INET6: proto_tree_add_item(message_tree, hf_lisp_tcp_message_rloc_ipv6, tvb, offset, INET6_ADDRLEN, ENC_NA); proto_item_append_text(tim, ", RLOC: %s", tvb_ip6_to_str(tvb, offset)); col_append_fstr(pinfo->cinfo, COL_INFO, " [%u] %s", iid, tvb_ip6_to_str(tvb, offset)); offset += INET6_ADDRLEN; data_len -= INET6_ADDRLEN; break; } break; case MEMBERSHIP_BASE + 7: case MEMBERSHIP_BASE + 8: /* Request ID (4 bytes) */ rid = tvb_get_ntohl(tvb, offset); proto_tree_add_item(message_tree, hf_lisp_tcp_message_rid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; data_len -= 4; proto_item_append_text(tim, ", Req ID: %u", rid); break; } if (data_len) { proto_tree_add_item(message_tree, hf_lisp_tcp_message_data, tvb, offset, data_len, ENC_NA); offset += data_len; expert_add_info_format(pinfo, message_tree, &ei_lisp_tcp_undecoded, "Work-in-progress"); } return offset; }
/* ----------------------------- from netatalk/etc/afpd/status.c */ static gint dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset) { proto_tree *sub_tree; proto_item *ti; guint16 ofs; guint16 flag; guint16 sign_ofs = 0; guint16 adr_ofs = 0; guint16 dir_ofs = 0; guint16 utf_ofs = 0; guint8 nbe; guint8 len; guint8 i; if (!tree) return offset; ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status"); tree = proto_item_add_subtree(ti, ett_dsi_status); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_MACHOFF, 2, "Machine offset: %d", ofs); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_VERSOFF, 2, "Version offset: %d", ofs); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_UAMSOFF, 2, "UAMS offset: %d", ofs); ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF); proto_tree_add_text(tree, tvb, offset +AFPSTATUS_ICONOFF, 2, "Icon offset: %d", ofs); ofs = offset +AFPSTATUS_FLAGOFF; ti = proto_tree_add_item(tree, hf_dsi_server_flag, tvb, ofs, 2, ENC_BIG_ENDIAN); sub_tree = proto_item_add_subtree(ti, ett_dsi_status_server_flag); proto_tree_add_item(sub_tree, hf_dsi_server_flag_copyfile , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_passwd , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_no_save_passwd, tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_msg , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_sig , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_tcpip , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_notify , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_reconnect , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_directory , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_utf8_name , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_uuid , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_ext_sleep , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree, hf_dsi_server_flag_fast_copy , tvb, ofs, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_dsi_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, ENC_ASCII|ENC_NA); flag = tvb_get_ntohs(tvb, ofs); if ((flag & AFPSRVRINFO_SRVSIGNATURE)) { ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN) +1; if ((ofs & 1)) ofs++; sign_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "Signature offset: %d", sign_ofs); sign_ofs += offset; if ((flag & AFPSRVRINFO_TCPIP)) { ofs += 2; adr_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %d", adr_ofs); adr_ofs += offset; } if ((flag & AFPSRVRINFO_SRVDIRECTORY)) { ofs += 2; dir_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %d", dir_ofs); dir_ofs += offset; } if ((flag & AFPSRVRINFO_SRVUTF8)) { ofs += 2; utf_ofs = tvb_get_ntohs(tvb, ofs); proto_tree_add_text(tree, tvb, ofs, 2, "UTF8 server name offset: %d", utf_ofs); utf_ofs += offset; } } ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF); if (ofs) proto_tree_add_item(tree, hf_dsi_server_type, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF); if (ofs) { nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "Version list: %d", nbe); ofs++; sub_tree = proto_item_add_subtree(ti, ett_dsi_vers); for (i = 0; i < nbe; i++) { len = tvb_get_guint8(tvb, ofs); proto_tree_add_item(sub_tree, hf_dsi_server_vers, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs += len + 1; } } ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF); if (ofs) { nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "UAMS list: %d", nbe); ofs++; sub_tree = proto_item_add_subtree(ti, ett_dsi_uams); for (i = 0; i < nbe; i++) { len = tvb_get_guint8(tvb, ofs); proto_tree_add_item(sub_tree, hf_dsi_server_uams, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs += len + 1; } } ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF); if (ofs) proto_tree_add_item(tree, hf_dsi_server_icon, tvb, ofs, 256, ENC_NA); if (sign_ofs) { proto_tree_add_item(tree, hf_dsi_server_signature, tvb, sign_ofs, 16, ENC_NA); } if (adr_ofs) { proto_tree *adr_tree; unsigned char *tmp; guint16 net; guint8 node; guint16 port; ofs = adr_ofs; nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "Address list: %d", nbe); ofs++; adr_tree = proto_item_add_subtree(ti, ett_dsi_addr); for (i = 0; i < nbe; i++) { guint8 type; len = tvb_get_guint8(tvb, ofs); type = tvb_get_guint8(tvb, ofs +1); switch (type) { case 1: /* IP */ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip: %s", tvb_ip_to_str(tvb, ofs+2)); break; case 2: /* IP + port */ port = tvb_get_ntohs(tvb, ofs+6); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s:%d", tvb_ip_to_str(tvb, ofs+2), port); break; case 3: /* DDP, atalk_addr_to_str want host order not network */ net = tvb_get_ntohs(tvb, ofs+2); node = tvb_get_guint8(tvb, ofs +4); port = tvb_get_guint8(tvb, ofs +5); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ddp: %u.%u:%u", net, node, port); break; case 4: /* DNS */ case 5: /* SSH tunnel */ if (len > 2) { tmp = tvb_get_string(wmem_packet_scope(), tvb, ofs +2, len -2); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "%s: %s", (type==4)?"dns":"ssh tunnel", tmp); break; } else { ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Malformed address type %d", type); } break; case 6: /* IP6 */ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip6: %s", tvb_ip6_to_str(tvb, ofs+2)); break; case 7: /* IP6 + 2bytes port */ port = tvb_get_ntohs(tvb, ofs+ 2+INET6_ADDRLEN); ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip6 %s:%d", tvb_ip6_to_str(tvb, ofs+2), port); break; default: ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Unknown type : %d", type); break; } len -= 2; sub_tree = proto_item_add_subtree(ti,ett_dsi_addr_line); proto_tree_add_item(sub_tree, hf_dsi_server_addr_len, tvb, ofs, 1, ENC_BIG_ENDIAN); ofs++; proto_tree_add_item(sub_tree, hf_dsi_server_addr_type, tvb, ofs, 1, ENC_BIG_ENDIAN); ofs++; proto_tree_add_item(sub_tree, hf_dsi_server_addr_value,tvb, ofs, len, ENC_NA); ofs += len; } } if (dir_ofs) { ofs = dir_ofs; nbe = tvb_get_guint8(tvb, ofs); ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %d", nbe); ofs++; sub_tree = proto_item_add_subtree(ti, ett_dsi_directory); for (i = 0; i < nbe; i++) { len = tvb_get_guint8(tvb, ofs); proto_tree_add_item(sub_tree, hf_dsi_server_directory, tvb, ofs, 1, ENC_ASCII|ENC_NA); ofs += len + 1; } } if (utf_ofs) { guint16 ulen; char *tmp; ofs = utf_ofs; ulen = tvb_get_ntohs(tvb, ofs); tmp = tvb_get_string(wmem_packet_scope(), tvb, ofs + 2, ulen); ti = proto_tree_add_text(tree, tvb, ofs, ulen + 2, "UTF8 server name: %s", tmp); sub_tree = proto_item_add_subtree(ti, ett_dsi_utf8_name); proto_tree_add_uint(sub_tree, hf_dsi_utf8_server_name_len, tvb, ofs, 2, ulen); ofs += 2; proto_tree_add_string(sub_tree, hf_dsi_utf8_server_name, tvb, ofs, ulen, tmp); ofs += ulen; } return ofs; }
static void dissect_xdmcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint version = -1, opcode = -1; gint offset = 0; proto_item *ti; proto_tree *xdmcp_tree = 0; version = tvb_get_ntohs(tvb, offset); if (version != XDMCP_PROTOCOL_VERSION) { /* Only version 1 exists, so this probably is not XDMCP at all... */ return; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "XDMCP"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { ti = proto_tree_add_item(tree, proto_xdmcp, tvb, offset, -1, FALSE); xdmcp_tree = proto_item_add_subtree(ti, ett_xdmcp); proto_tree_add_uint(xdmcp_tree, hf_xdmcp_version, tvb, offset, 2, version); } offset += 2; opcode = tvb_get_ntohs(tvb, offset); if (tree) { proto_tree_add_uint(xdmcp_tree, hf_xdmcp_opcode, tvb, offset, 2, opcode); } offset += 2; if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, opcode_vals, "Unknown (0x%04x)")); } if (tree) { proto_tree_add_item(xdmcp_tree, hf_xdmcp_length, tvb, offset, 2, FALSE); offset += 2; switch (opcode) { case XDMCP_FORWARD_QUERY: { gint alen, plen; alen = tvb_get_ntohs(tvb, offset); /* I have never seen anything except IPv4 addresses here, * but in theory the protocol should support other address * families. */ if (alen == 4) { proto_tree_add_text(xdmcp_tree, tvb, offset, alen+2, "Client address: %s", tvb_ip_to_str(tvb, offset+2)); offset += 6; } else if (alen == 16) { proto_tree_add_text(xdmcp_tree, tvb, offset, alen+2, "Client address: %s", tvb_ip6_to_str(tvb, offset+2)); offset += 18; } else { offset += xdmcp_add_bytes(xdmcp_tree, "Client address", tvb, offset); } plen = tvb_get_ntohs(tvb, offset); if (plen == 2) { proto_tree_add_text(xdmcp_tree, tvb, offset, plen+2, "Client port: %u", tvb_get_ntohs(tvb, offset+2)); offset += 4; } else { offset += xdmcp_add_bytes(xdmcp_tree, "Client port", tvb, offset); } } /* fall-through */ case XDMCP_BROADCAST_QUERY: case XDMCP_QUERY: case XDMCP_INDIRECT_QUERY: offset += xdmcp_add_authentication_names(xdmcp_tree, tvb, offset); break; case XDMCP_WILLING: offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); break; case XDMCP_UNWILLING: offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); break; case XDMCP_REQUEST: { proto_tree *clist_tree; proto_item *clist_ti; gint ctypes_len, caddrs_len, n; gint ctypes_start_offset, caddrs_offset; proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb, offset, 2, FALSE); offset += 2; ctypes_len = tvb_get_guint8(tvb, offset); ctypes_start_offset = offset; caddrs_offset = offset + 1 + 2*ctypes_len; caddrs_len = tvb_get_guint8(tvb, caddrs_offset); if (ctypes_len != caddrs_len) { proto_tree_add_text(xdmcp_tree, NULL, 0, 0, "Error: Connection type/address arrays don't match"); return; } clist_ti = proto_tree_add_text(xdmcp_tree, tvb, ctypes_start_offset, -1, "Connections (%d)", ctypes_len); clist_tree = proto_item_add_subtree(clist_ti, ett_xdmcp_connections); offset++; caddrs_offset++; n = 1; while (ctypes_len > 0) { proto_item *connection_ti; proto_tree *connection_tree; const char *ip_string; gint alen; gint ctype = tvb_get_ntohs(tvb, offset); offset += 2; alen = tvb_get_ntohs(tvb, caddrs_offset); caddrs_offset += 2; if ((ctype == 0) && (alen == 4)) { ip_string = tvb_ip_to_str(tvb, caddrs_offset); } else if ((ctype == 6) && (alen == 16)) { ip_string = tvb_ip6_to_str(tvb, caddrs_offset); } else { ip_string = NULL; } connection_ti = proto_tree_add_text(clist_tree, NULL, 0, 0, "Connection %d%s%s", n, (ip_string ? ": " : ""), (ip_string ? ip_string : "")); connection_tree = proto_item_add_subtree(connection_ti, ett_xdmcp_connection); proto_tree_add_text(connection_tree, tvb, offset-2, 2, "Type: %s", val_to_str(ctype, family_vals, "Unknown (0x%04x)")); if (ip_string) { proto_tree_add_text(connection_tree, tvb, caddrs_offset-2, alen+2, "Address: %s", ip_string); } else { proto_tree_add_text(connection_tree, tvb, caddrs_offset-2, alen+2, "Address: (%u byte%s)", alen, plurality(alen, "", "s")); } caddrs_offset += alen; ctypes_len--; n++; } offset = caddrs_offset; proto_item_set_len(clist_ti, offset - ctypes_start_offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, "Authentication data", tvb, offset); offset += xdmcp_add_authorization_names(xdmcp_tree, tvb, offset); offset += xdmcp_add_text(xdmcp_tree, "Manufacturer display ID", tvb, offset); break; } case XDMCP_ACCEPT: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, FALSE); offset += 4; offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, "Authentication data", tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authorization_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, "Authorization data", tvb, offset); break; case XDMCP_DECLINE: offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, "Authentication data", tvb, offset); break; case XDMCP_MANAGE: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, FALSE); offset += 4; proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb, offset, 2, FALSE); offset += 2; offset += xdmcp_add_text(xdmcp_tree, "Display class", tvb, offset); break; case XDMCP_REFUSE: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, FALSE); offset += 4; break; case XDMCP_FAILED: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, FALSE); offset += 4; offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); break; case XDMCP_KEEPALIVE: proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb, offset, 2, FALSE); offset += 2; proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, FALSE); offset += 4; break; case XDMCP_ALIVE: proto_tree_add_text(xdmcp_tree, tvb, offset, 1, "Session running: %s", (tvb_get_guint8(tvb, offset) ? "Yes" : "No")); offset++; proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, FALSE); offset += 4; break; } } }
/* Code to actually dissect the packets */ static int rsip_parameter(tvbuff_t *tvb, proto_tree *rsip_tree, int off, int eoff) { int consumed, i, paramleft; guint8 addrtype, flowpolicy, method, number, paramtype, tuntype; guint16 error, ind, paramlen, portnum; guint32 bid, cid, leasetm, msgc; proto_tree *p_tree, *v_tree; proto_item *pti, *vti; /* XXX */ if (off >= eoff) return 0; paramtype = tvb_get_guint8(tvb, off); paramlen = tvb_get_ntohs(tvb, off + 1); p_tree = proto_tree_add_subtree(rsip_tree, tvb, off, 3 + paramlen, ett_rsip_param, &pti, val_to_str(paramtype, param_type_vals, "Unknown (%d)")); proto_tree_add_item(p_tree, hf_rsip_parameter_type, tvb, off, 1, ENC_BIG_ENDIAN); proto_tree_add_item(p_tree, hf_rsip_parameter_length, tvb, off + 1, 2, ENC_BIG_ENDIAN); consumed = 3; if (paramlen == 0) return consumed; vti = proto_tree_add_item(p_tree, hf_rsip_parameter_value, tvb, off + 3, paramlen, ENC_NA); v_tree = proto_item_add_subtree(vti, ett_rsip_param_val); switch (paramtype) { case 1: /* Address */ proto_tree_add_item(v_tree, hf_rsip_parameter_address_type, tvb, off + 3, 1, ENC_BIG_ENDIAN); addrtype = tvb_get_guint8(tvb, off + 3); switch (addrtype) { case 0: /* Reserved */ break; case 1: /* IPv4 */ if (paramlen - 1 > 0) { proto_tree_add_item(v_tree, hf_rsip_parameter_address_ipv4, tvb, off + 4, paramlen - 1, ENC_BIG_ENDIAN); proto_item_append_text(pti, ": %s", tvb_ip_to_str(tvb, off + 4)); } else proto_item_append_text(pti, ": Any IPv4 Address"); break; case 2: /* IPv4 netmask */ if (paramlen - 1 > 0) { proto_tree_add_item(v_tree, hf_rsip_parameter_address_ipv4_netmask, tvb, off + 4, paramlen - 1, ENC_BIG_ENDIAN); proto_item_append_text(pti, "(netmask): %s", tvb_ip_to_str(tvb, off + 4)); } else proto_item_append_text(pti, ": Any IPv4 Netmask"); break; case 3: /* IPv6 */ if (paramlen - 1 > 0) { proto_tree_add_item(v_tree, hf_rsip_parameter_address_ipv6, tvb, off + 4, paramlen - 1, ENC_NA); proto_item_append_text(pti, ": %s", tvb_ip6_to_str(tvb, off + 4)); } else proto_item_append_text(pti, ": Any IPv6 Address"); break; case 4: /* FQDN */ if (paramlen - 1 > 0) { proto_tree_add_item(v_tree, hf_rsip_parameter_address_fqdn, tvb, off + 4, paramlen - 1, ENC_ASCII|ENC_NA); proto_item_append_text(pti, ": %s", tvb_format_text(tvb, off + 4, paramlen - 1)); } else proto_item_append_text(pti, ": Any Fully Qualified Domain Name"); break; default: proto_item_append_text(pti, ": Unknown Address Type"); break; } break; case 2: /* Ports */ proto_tree_add_item(v_tree, hf_rsip_parameter_ports_number, tvb, off + 3, 1, ENC_BIG_ENDIAN); number = tvb_get_guint8(tvb, off + 3); if (paramlen == 1) { switch (number) { case 0: proto_item_append_text(pti, ": Unspecified"); break; case 1: proto_item_append_text(pti, ": Any port"); break; default: proto_item_append_text(pti, ": Any %d ports", number); break; } } else { portnum = tvb_get_ntohs(tvb, off + 4); if (number == 1) { proto_tree_add_item(v_tree, hf_rsip_parameter_ports_port_number, tvb, off + 4, 2, ENC_BIG_ENDIAN); } else { paramleft = paramlen - 1; if (paramleft == 2) { proto_tree_add_uint_format_value(v_tree, hf_rsip_parameter_ports_port_number, tvb, off + 4, 2, portnum, "%d - %d", portnum, portnum + number); proto_item_append_text(pti, ": %d - %d", portnum, portnum + number); } else { for (i = off + 4; paramleft > 0; i += 2, paramleft -= 2) proto_tree_add_item(v_tree, hf_rsip_parameter_ports_port_number, tvb, i, 2, ENC_BIG_ENDIAN); proto_item_append_text(pti, ": List of %d Ports", number); } } } break; case 3: /* Lease Time */ /* XXX if paramlen != 4 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_lease_time, tvb, off + 3, paramlen, ENC_BIG_ENDIAN); leasetm = tvb_get_ntohl(tvb, off + 3); proto_item_append_text(pti, ": %d seconds", leasetm); break; case 4: /* Client ID */ /* XXX if paramlen != 4 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_client_id, tvb, off + 3, paramlen, ENC_BIG_ENDIAN); cid = tvb_get_ntohl(tvb, off + 3); proto_item_append_text(pti, ": %d", cid); break; case 5: /* Bind ID */ /* XXX if paramlen != 4 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_bind_id, tvb, off + 3, paramlen, ENC_BIG_ENDIAN); bid = tvb_get_ntohl(tvb, off + 3); proto_item_append_text(pti, ": %d", bid); break; case 6: /* Tunnel Type */ /* XXX if paramlen != 1 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_tunnel_type, tvb, off + 3, paramlen, ENC_BIG_ENDIAN); tuntype = tvb_get_guint8(tvb, off + 3); proto_item_append_text(pti, ": %s", val_to_str(tuntype, tunnel_type_vals, "Unknown Tunnel Type (%d)")); break; case 7: /* RSIP Method */ /* XXX if paramlen != 1 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_method, tvb, off + 3, paramlen, ENC_BIG_ENDIAN); method = tvb_get_guint8(tvb, off + 3); proto_item_append_text(pti, ": %s", val_to_str(method, method_vals, "Unknown RSIP Method (%d)")); break; case 8: /* Error */ /* XXX if paramlen != 2 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_error, tvb, off + 3, paramlen, ENC_BIG_ENDIAN); error = tvb_get_ntohs(tvb, off + 3); proto_item_append_text(pti, ": %s", val_to_str(error, error_number_vals, "Undefined Error (%d)")); break; case 9: /* Flow Policy */ /* XXX if paramlen != 2 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_flow_policy_local, tvb, off + 3, 1, ENC_BIG_ENDIAN); flowpolicy = tvb_get_guint8(tvb, off + 3); proto_item_append_text(pti, ": %s", val_to_str(flowpolicy, lcl_flow_policy_vals, "Undefined Local Flow Policy (%d)")); proto_tree_add_item(v_tree, hf_rsip_parameter_flow_policy_remote, tvb, off + 4, 1, ENC_BIG_ENDIAN); flowpolicy = tvb_get_guint8(tvb, off + 4); proto_item_append_text(pti, "/%s", val_to_str(flowpolicy, rmt_flow_policy_vals, "Undefined Remote Flow Policy (%d)")); break; case 10: /* Indicator */ /* XXX if paramlen != 2 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_indicator, tvb, off + 3, 2, ENC_BIG_ENDIAN); ind = tvb_get_ntohs(tvb, off + 3); proto_item_append_text(pti, ": %d", ind); break; case 11: /* Message Counter */ /* XXX if paramlen != 4 we've got a protocol violation */ proto_tree_add_item(v_tree, hf_rsip_parameter_message_counter, tvb, off + 3, 4, ENC_BIG_ENDIAN); msgc = tvb_get_ntohl(tvb, off + 3); proto_item_append_text(pti, ": %d", msgc); break; case 12: /* Vendor Specific */ proto_tree_add_item(v_tree, hf_rsip_parameter_vendor_specific_vendor_id, tvb, off + 3, 2, ENC_BIG_ENDIAN); proto_tree_add_item(v_tree, hf_rsip_parameter_vendor_specific_subtype, tvb, off + 5, 2, ENC_BIG_ENDIAN); proto_tree_add_item(v_tree, hf_rsip_parameter_vendor_specific_value, tvb, off + 9, paramlen - 4, ENC_NA); break; case 22: /* SPI */ proto_tree_add_item(v_tree, hf_rsip_parameter_spi_number, tvb, off + 3, 2, ENC_BIG_ENDIAN); /* XXX need loop? */ proto_tree_add_item(v_tree, hf_rsip_parameter_spi, tvb, off + 5, 4, ENC_BIG_ENDIAN); break; default: break; } consumed += paramlen; return consumed; }
static void dissect_xdmcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint version = -1, opcode = -1; gint offset = 0; proto_item *ti; proto_tree *xdmcp_tree = 0; version = tvb_get_ntohs(tvb, offset); if (version != XDMCP_PROTOCOL_VERSION) { /* Only version 1 exists, so this probably is not XDMCP at all... */ return; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "XDMCP"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_xdmcp, tvb, offset, -1, ENC_NA); xdmcp_tree = proto_item_add_subtree(ti, ett_xdmcp); proto_tree_add_uint(xdmcp_tree, hf_xdmcp_version, tvb, offset, 2, version); offset += 2; opcode = tvb_get_ntohs(tvb, offset); if (tree) { proto_tree_add_uint(xdmcp_tree, hf_xdmcp_opcode, tvb, offset, 2, opcode); } offset += 2; if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, opcode_vals, "Unknown (0x%04x)")); } if (tree) { proto_tree_add_item(xdmcp_tree, hf_xdmcp_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; switch (opcode) { case XDMCP_FORWARD_QUERY: { gint alen, plen; alen = tvb_get_ntohs(tvb, offset); /* I have never seen anything except IPv4 addresses here, * but in theory the protocol should support other address * families. */ if (alen == 4) { proto_tree_add_item(xdmcp_tree, hf_xdmcp_client_address_ipv4, tvb, offset+2, alen, ENC_BIG_ENDIAN); offset += 6; } else if (alen == 16) { proto_tree_add_item(xdmcp_tree, hf_xdmcp_client_address_ipv6, tvb, offset+2, alen, ENC_BIG_ENDIAN); offset += 18; } else { offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_client_address_bytes, hf_xdmcp_client_address_bytes_len, tvb, offset); } plen = tvb_get_ntohs(tvb, offset); if (plen == 2) { proto_tree_add_item(xdmcp_tree, hf_xdmcp_client_port_u16, tvb, offset+2, plen, ENC_BIG_ENDIAN); offset += 4; } else { offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_client_port_bytes, hf_xdmcp_client_port_len, tvb, offset); } } /* fall-through */ case XDMCP_BROADCAST_QUERY: case XDMCP_QUERY: case XDMCP_INDIRECT_QUERY: offset += xdmcp_add_authentication_names(xdmcp_tree, tvb, offset); break; case XDMCP_WILLING: offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); break; case XDMCP_UNWILLING: offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); break; case XDMCP_REQUEST: { proto_tree *clist_tree; proto_item *clist_ti; gint ctypes_len, caddrs_len, n; gint ctypes_start_offset, caddrs_offset; ti = proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; ctypes_len = tvb_get_guint8(tvb, offset); ctypes_start_offset = offset; caddrs_offset = offset + 1 + 2*ctypes_len; caddrs_len = tvb_get_guint8(tvb, caddrs_offset); if (ctypes_len != caddrs_len) { expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Error: Connection type/address arrays don't match"); return; } clist_ti = proto_tree_add_text(xdmcp_tree, tvb, ctypes_start_offset, -1, "Connections (%d)", ctypes_len); clist_tree = proto_item_add_subtree(clist_ti, ett_xdmcp_connections); offset++; caddrs_offset++; n = 1; while (ctypes_len > 0) { proto_item *connection_ti; proto_tree *connection_tree; gint alen; gint ctype = tvb_get_ntohs(tvb, offset); offset += 2; alen = tvb_get_ntohs(tvb, caddrs_offset); caddrs_offset += 2; connection_ti = proto_tree_add_text(clist_tree, NULL, 0, 0, "Connection %d", n); connection_tree = proto_item_add_subtree(connection_ti, ett_xdmcp_connection); proto_tree_add_item(connection_tree, hf_xdmcp_connection_type, tvb, offset-2, 2, ENC_BIG_ENDIAN); if ((ctype == 0) && (alen == 4)) { proto_tree_add_item(connection_tree, hf_xdmcp_connection_address_ipv4, tvb, caddrs_offset, alen, ENC_BIG_ENDIAN); proto_item_append_text(connection_ti, ": %s", tvb_ip_to_str(tvb, caddrs_offset)); } else if ((ctype == 6) && (alen == 16)) { proto_tree_add_item(connection_tree, hf_xdmcp_connection_address_ipv6, tvb, caddrs_offset, alen, ENC_BIG_ENDIAN); proto_item_append_text(connection_ti, ": %s", tvb_ip6_to_str(tvb, caddrs_offset)); } else { proto_tree_add_item(connection_tree, hf_xdmcp_connection_address_bytes, tvb, caddrs_offset, alen, ENC_NA); } caddrs_offset += alen; ctypes_len--; n++; } offset = caddrs_offset; proto_item_set_len(clist_ti, offset - ctypes_start_offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authentication_data, hf_xdmcp_authentication_data_len, tvb, offset); offset += xdmcp_add_authorization_names(xdmcp_tree, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_manufacturer_display_id, hf_xdmcp_manufacturer_display_id_len, tvb, offset); break; } case XDMCP_ACCEPT: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authentication_data, hf_xdmcp_authentication_data_len, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authorization_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authorization_data, hf_xdmcp_authorization_data_len, tvb, offset); break; case XDMCP_DECLINE: offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name, tvb, offset); offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_authentication_data, hf_xdmcp_authentication_data_len, tvb, offset); break; case XDMCP_MANAGE: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; offset += xdmcp_add_bytes(xdmcp_tree, hf_xdmcp_display_class, hf_xdmcp_display_class_len, tvb, offset); break; case XDMCP_REFUSE: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case XDMCP_FAILED: proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status, tvb, offset); break; case XDMCP_KEEPALIVE: proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case XDMCP_ALIVE: { guint8 session_running = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format(xdmcp_tree, hf_xdmcp_session_running, tvb, offset, 1, session_running, "Session running: %s", session_running ? "Yes" : "No"); offset++; proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } break; } } }
static void dissect_ath(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; /* various lengths as reported in the packet itself */ guint8 hlen = 0; gint32 clen = 0; gint32 dlen = 0; gint32 plen = 0; /* detect the Tribes (Tomcat) version */ gint tribes_version_mark; /* store the info */ const gchar *info_srcaddr = ""; const gchar *info_domain = ""; const gchar *info_command = ""; proto_item *ti, *hlen_item; proto_tree *ath_tree; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATH"); /* Clear out stuff in the info column */ col_clear(pinfo->cinfo,COL_INFO); ti = proto_tree_add_item(tree, proto_ath, tvb, 0, -1, ENC_NA); ath_tree = proto_item_add_subtree(ti, ett_ath); /* Determine the Tribes version, which means determining the Tomcat version. * There are 2 versions : one for Tomcat 6, and one for Tomcat 7/8 * We know that Tomcat 6 packets end with "-E" (Ox2d 0x45 or 11589 in decimal) * and Tomcat 7/8 packets end with "Ox01 0x00" (256 in decimal) * This is why we read these 2 last bytes of the packet */ tribes_version_mark = tvb_get_ntohs(tvb, tvb_reported_length(tvb) - 2); /* dissecting a Tomcat 6 packet */ if (tribes_version_mark == 11589) { /* "-E" */ /* BEGIN */ proto_tree_add_item(ath_tree, hf_ath_begin, tvb, offset, 8, ENC_ASCII|ENC_NA); offset += 8; /* LENGTH */ proto_tree_add_item(ath_tree, hf_ath_length, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* ALIVE TIME */ proto_tree_add_item(ath_tree, hf_ath_alive, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* PORT */ proto_tree_add_item(ath_tree, hf_ath_port, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* SECURE PORT */ proto_tree_add_item(ath_tree, hf_ath_sport, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* HOST LENGTH */ hlen_item = proto_tree_add_item(ath_tree, hf_ath_hlen, tvb, offset, 1, ENC_BIG_ENDIAN); hlen = tvb_get_guint8(tvb, offset); offset += 1; /* HOST */ if (hlen == 4) { proto_tree_add_item(ath_tree, hf_ath_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); info_srcaddr = tvb_ip_to_str(tvb, offset); } else if (hlen == 6) { proto_tree_add_item(ath_tree, hf_ath_ipv6, tvb, offset, 6, ENC_NA); info_srcaddr = tvb_ip6_to_str(tvb, offset); } else { expert_add_info(pinfo, hlen_item, &ei_ath_hlen_invalid); } offset += hlen; /* COMMAND LENGTH */ proto_tree_add_item_ret_int(ath_tree, hf_ath_clen, tvb, offset, 4, ENC_BIG_ENDIAN, &clen); offset += 4; /* COMMAND */ proto_tree_add_item(ath_tree, hf_ath_comm, tvb, offset, clen, ENC_ASCII|ENC_NA); if (clen != -1) info_command = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, clen, ENC_ASCII); offset += clen; /* DOMAIN LENGTH */ proto_tree_add_item_ret_int(ath_tree, hf_ath_dlen, tvb, offset, 4, ENC_BIG_ENDIAN, &dlen); offset += 4; /* DOMAIN */ proto_tree_add_item(ath_tree, hf_ath_domain, tvb, offset, dlen, ENC_ASCII|ENC_NA); if (dlen != 0) info_domain = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, dlen, ENC_ASCII); offset += dlen; /* UNIQUEID */ proto_tree_add_item(ath_tree, hf_ath_unique, tvb, offset, 16, ENC_NA); offset += 16; /* PAYLOAD LENGTH */ proto_tree_add_item_ret_int(ath_tree, hf_ath_plen, tvb, offset, 4, ENC_BIG_ENDIAN, &plen); offset += 4; /* PAYLOAD */ proto_tree_add_item(ath_tree, hf_ath_payload, tvb, offset, plen, ENC_ASCII|ENC_NA); offset += plen; /* END */ proto_tree_add_item(ath_tree, hf_ath_end, tvb, offset, 8, ENC_ASCII|ENC_NA); } /* dissecting a Tomcat 7/8 packet */ else if (tribes_version_mark == 256) { /* BEGIN */ proto_tree_add_item(ath_tree, hf_ath_begin, tvb, offset, 8, ENC_ASCII|ENC_NA); offset += 8; proto_tree_add_item(ath_tree, hf_ath_padding, tvb, offset, 2, ENC_ASCII|ENC_NA); offset += 2; /* LENGTH */ proto_tree_add_item(ath_tree, hf_ath_length, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* ALIVE TIME */ proto_tree_add_item(ath_tree, hf_ath_alive, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* PORT */ proto_tree_add_item(ath_tree, hf_ath_port, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* SECURE PORT */ proto_tree_add_item(ath_tree, hf_ath_sport, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* UDP PORT, only in Tomcat 7/8 */ proto_tree_add_item(ath_tree, hf_ath_uport, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* HOST LENGTH */ hlen_item = proto_tree_add_item(ath_tree, hf_ath_hlen, tvb, offset, 1, ENC_BIG_ENDIAN); hlen = tvb_get_guint8(tvb, offset); offset += 1; /* HOST */ if (hlen == 4) { proto_tree_add_item(ath_tree, hf_ath_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); info_srcaddr = tvb_ip_to_str(tvb, offset); } else if (hlen == 6) { proto_tree_add_item(ath_tree, hf_ath_ipv6, tvb, offset, 6, ENC_NA); info_srcaddr = tvb_ip6_to_str(tvb, offset); } else { expert_add_info(pinfo, hlen_item, &ei_ath_hlen_invalid); } offset += hlen; /* COMMAND LENGTH */ proto_tree_add_item_ret_int(ath_tree, hf_ath_clen, tvb, offset, 4, ENC_BIG_ENDIAN, &clen); offset += 4; /* COMMAND */ proto_tree_add_item(ath_tree, hf_ath_comm, tvb, offset, clen, ENC_ASCII|ENC_NA); if (clen != -1) info_command = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, clen, ENC_ASCII); offset += clen; /* DOMAIN LENGTH */ proto_tree_add_item_ret_int(ath_tree, hf_ath_dlen, tvb, offset, 4, ENC_BIG_ENDIAN, &dlen); offset += 4; /* DOMAIN */ proto_tree_add_item(ath_tree, hf_ath_domain, tvb, offset, dlen, ENC_ASCII|ENC_NA); if (dlen != 0) info_domain = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, dlen, ENC_ASCII); offset += dlen; /* UNIQUEID */ proto_tree_add_item(ath_tree, hf_ath_unique, tvb, offset, 16, ENC_NA); offset += 16; /* PAYLOAD LENGTH */ proto_tree_add_item_ret_int(ath_tree, hf_ath_plen, tvb, offset, 4, ENC_BIG_ENDIAN, &plen); offset += 4; /* PAYLOAD */ proto_tree_add_item(ath_tree, hf_ath_payload, tvb, offset, plen, ENC_ASCII|ENC_NA); offset += plen; /* END */ proto_tree_add_item(ath_tree, hf_ath_end, tvb, offset, 8, ENC_ASCII|ENC_NA); } else { proto_tree_add_expert(tree, pinfo, &ei_ath_hmark_invalid, tvb, offset, -1); return; } /* set the INFO column, and we're done ! */ if (strcmp(info_command, "") != 0) { if (strcmp(info_command, "BABY-ALEX") == 0) { if (strcmp(info_domain, "") != 0) { col_append_fstr(pinfo->cinfo, COL_INFO, "%s is leaving domain %s", info_srcaddr, info_domain); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "%s is leaving default domain", info_srcaddr); } } else { if (strcmp(info_domain, "") != 0) { col_append_fstr(pinfo->cinfo, COL_INFO, "Heartbeat from %s to domain %s", info_srcaddr, info_domain); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "Heartbeat from %s to default domain", info_srcaddr); } } } else { if (strcmp(info_domain, "") != 0) { col_append_fstr(pinfo->cinfo, COL_INFO, "Heartbeat from %s to domain %s", info_srcaddr, info_domain); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "Heartbeat from %s to default domain", info_srcaddr); } } }