static int dissect_msnip_gm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { guint8 count; /* group count */ count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(parent_tree, hf_count, tvb, offset, 1, count); offset += 1; /* checksum */ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; /* holdtime */ proto_tree_add_uint(parent_tree, hf_holdtime, tvb, offset, 4, count); offset += 4; while (count--) { proto_tree *tree; proto_item *item; guint32 maddr; guint8 masklen; int old_offset = offset; item = proto_tree_add_item(parent_tree, hf_groups, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_groups); /* multicast group */ maddr = tvb_get_ipv4(tvb, offset); proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, maddr); offset += 4; /* mask length */ masklen = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_mask, tvb, offset, 1, masklen); offset += 1; /* skip 3 unused bytes */ offset += 3; if (item) { proto_item_set_text(item,"Group: %s/%d", ip_to_str((guint8 *)&maddr), masklen); proto_item_set_len(item, offset-old_offset); } } return offset; }
static int dissect_mrdisc_mrst(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { /* skip reserved byte */ offset += 1; /* checksum */ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; return offset; }
static int dissect_msnip_rmr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { guint8 count; /* group count */ count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(parent_tree, hf_count, tvb, offset, 1, count); offset += 1; /* checksum */ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; while (count--) { proto_tree *tree; proto_item *item; guint8 rec_type; guint32 maddr; int old_offset = offset; item = proto_tree_add_item(parent_tree, hf_groups, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_groups); /* record type */ rec_type = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_rec_type, tvb, offset, 1, rec_type); offset += 1; /* skip 3 unused bytes */ offset += 3; /* multicast group */ maddr = tvb_get_ipv4(tvb, offset); proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, maddr); offset += 4; if (item) { proto_item_set_text(item,"Group: %s %s", ip_to_str((guint8 *)&maddr), val_to_str(rec_type, msnip_rec_types, "Unknown Type:0x%02x")); proto_item_set_len(item, offset-old_offset); } } return offset; }
static int dissect_msnip_is(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { /* skip reserved byte */ offset += 1; /* checksum */ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; /* 16 bit holdtime */ proto_tree_add_uint(parent_tree, hf_holdtime16, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; /* Generation ID */ proto_tree_add_uint(parent_tree, hf_genid, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset += 2; return offset; }
/* This function is only called from the IGMP dissector */ int dissect_rgmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; guint8 type; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_rgmp))) { /* 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); } item = proto_tree_add_item(parent_tree, proto_rgmp, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_rgmp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "RGMP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, rgmp_types, "Unknown Type: 0x%02x")); } proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); offset += 1; /* reserved */ offset += 1; igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; return offset; }
/* This function is only called from the IGMP dissector */ int dissect_igap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { proto_tree *tree; proto_item *item; guint8 type, tsecs, subtype, asize, msize; guchar account[ACCOUNT_SIZE+1], message[MESSAGE_SIZE+1]; if (!proto_is_protocol_enabled(find_protocol_by_id(proto_igap))) { /* 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); } item = proto_tree_add_item(parent_tree, proto_igap, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_igap); col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGAP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, igap_types, "Unknown Type: 0x%02x")); proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); offset += 1; tsecs = tvb_get_guint8(tvb, offset); proto_tree_add_uint_format_value(tree, hf_max_resp, tvb, offset, 1, tsecs, "%.1f sec (0x%02x)", tsecs * 0.1, tsecs); offset += 1; igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_uint(tree, hf_version, tvb, offset, 1, tvb_get_guint8(tvb, offset)); offset += 1; subtype = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_subtype, tvb, offset, 1, subtype); offset += 2; proto_tree_add_uint(tree, hf_challengeid, tvb, offset, 1, tvb_get_guint8(tvb, offset)); offset += 1; asize = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_asize, tvb, offset, 1, asize); offset += 1; msize = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_msize, tvb, offset, 1, msize); offset += 3; if (asize > 0) { if (asize > ACCOUNT_SIZE) { /* Bogus account size. XXX - flag this? */ asize = ACCOUNT_SIZE; } tvb_memcpy(tvb, account, offset, asize); account[asize] = '\0'; proto_tree_add_string(tree, hf_account, tvb, offset, asize, account); } offset += ACCOUNT_SIZE; if (msize > 0) { if (msize > MESSAGE_SIZE) { /* Bogus message size. XXX - flag this? */ msize = MESSAGE_SIZE; } tvb_memcpy(tvb, message, offset, msize); switch (subtype) { case IGAP_SUBTYPE_PASSWORD_JOIN: case IGAP_SUBTYPE_PASSWORD_LEAVE: /* Challenge field is user's password */ message[msize] = '\0'; proto_tree_add_string(tree, hf_igap_user_password, tvb, offset, msize, message); break; case IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN: case IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE: /* Challenge field is the results of MD5 calculation */ proto_tree_add_item(tree, hf_igap_result_of_md5_calculation, tvb, offset, msize, ENC_NA); break; case IGAP_SUBTYPE_CHALLENGE: /* Challenge field is the challenge value */ proto_tree_add_item(tree, hf_igap_challenge, tvb, offset, msize, ENC_NA); break; case IGAP_SUBTYPE_AUTH_MESSAGE: /* Challenge field indicates the result of the authenticaion */ proto_tree_add_uint(tree, hf_igap_authentication_result, tvb, offset, msize, message[0]); break; case IGAP_SUBTYPE_ACCOUNTING_MESSAGE: /* Challenge field indicates the accounting status */ proto_tree_add_uint(tree, hf_igap_accounting_status, tvb, offset, msize, message[0]); break; default: proto_tree_add_item(tree, hf_igap_unknown_message, tvb, offset, msize, ENC_NA); } } offset += MESSAGE_SIZE; if (item) proto_item_set_len(item, offset); return offset; }
static int dissect_dvmrp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { guint8 code; guint8 af=2; /* default */ /* version */ proto_tree_add_uint(parent_tree, hf_version, tvb, 0, 0, 1); /* type of command */ proto_tree_add_uint(parent_tree, hf_type, tvb, offset, 1, 0x13); offset += 1; /* code */ code = tvb_get_guint8(tvb, offset); proto_tree_add_uint(parent_tree, hf_code_v1, tvb, offset, 1, code); offset += 1; col_add_fstr(pinfo->cinfo, COL_INFO, "V%d %s",1 ,val_to_str(code, code_v1, "Unknown Type:0x%02x")); /* checksum */ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; /* decode all the v1 commands */ while (tvb_reported_length_remaining(tvb, offset) > 0) { proto_tree *tree; proto_item *item; guint8 cmd,count; int old_offset = offset; item = proto_tree_add_item(parent_tree, hf_commands, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_commands); cmd = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_command, tvb, offset, 1, cmd); offset += 1; switch (cmd){ case V1_COMMAND_NULL: offset += 1; /* skip ignored/pad byte*/ if (item) { proto_item_set_text(item, "Command: NULL"); } break; case V1_COMMAND_AFI: af = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_afi, tvb, offset, 1, af); offset += 1; if (item) { proto_item_set_text(item, "%s: %s", val_to_str(cmd, command, "Unknown Command:0x%02x"), val_to_str(af, afi, "Unknown Family:0x%02x") ); } break; case V1_COMMAND_SUBNETMASK: count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_count, tvb, offset, 1, count); offset += 1; if (count) { /* must be 0 or 1 */ proto_tree_add_item(tree, hf_netmask, tvb, offset, 4, ENC_BIG_ENDIAN); if (item) { proto_item_set_text(item, "%s: %d.%d.%d.%d", val_to_str(cmd, command, "Unknown Command:0x%02x"), tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3)); } offset += 4; } else { if (item) { proto_item_set_text(item, "%s: <no mask supplied>", val_to_str(cmd, command, "Unknown Command:0x%02x")); } } break; case V1_COMMAND_METRIC: proto_tree_add_item(tree, hf_metric, tvb, offset, 1, ENC_BIG_ENDIAN); if (item) { proto_item_set_text(item, "%s: %d", val_to_str(cmd, command, "Unknown Command:0x%02x"), tvb_get_guint8(tvb, offset)); } offset += 1; break; case V1_COMMAND_FLAGS0: count = tvb_get_guint8(tvb, offset); proto_tree_add_boolean(tree, hf_dest_unr, tvb, offset, 1, count); proto_tree_add_boolean(tree, hf_split_horiz, tvb, offset, 1, count); if (item) { proto_item_set_text(item, "%s: 0x%02x", val_to_str(cmd, command, "Unknown Command:0x%02x"), count); } offset += 1; break; case V1_COMMAND_INFINITY: proto_tree_add_item(tree, hf_infinity, tvb, offset, 1, ENC_BIG_ENDIAN); if (item) { proto_item_set_text(item, "%s: %d", val_to_str(cmd, command, "Unknown Command:0x%02x"), tvb_get_guint8(tvb, offset)); } offset += 1; break; case V1_COMMAND_DA: case V1_COMMAND_RDA: /* same as DA */ count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_count, tvb, offset, 1, count); offset += 1; while (count--) { proto_tree_add_item(tree, hf_daddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } if (item) { proto_item_set_text(item, "%s", val_to_str(cmd, command, "Unknown Command:0x%02x")); } break; case V1_COMMAND_NMR: count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_count, tvb, offset, 1, count); offset += 1; while (count--) { proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_hold, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } if (item) { proto_item_set_text(item, "%s", val_to_str(cmd, command, "Unknown Command:0x%02x")); } break; case V1_COMMAND_NMR_CANCEL: count = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_count, tvb, offset, 1, count); offset += 1; while (count--) { proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } if (item) { proto_item_set_text(item, "%s", val_to_str(cmd, command, "Unknown Command:0x%02x")); } break; } proto_item_set_len(item, offset-old_offset); } return offset; }
static int dissect_dvmrp_v3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { guint8 code; /* version */ proto_tree_add_uint(parent_tree, hf_version, tvb, 0, 0, 3); /* type of command */ proto_tree_add_uint(parent_tree, hf_type, tvb, offset, 1, 0x13); offset += 1; /* code */ code = tvb_get_guint8(tvb, offset); proto_tree_add_uint(parent_tree, hf_code_v3, tvb, offset, 1, code); offset += 1; col_add_fstr(pinfo->cinfo, COL_INFO, "V%d %s",3 ,val_to_str(code, code_v3, "Unknown Type:0x%02x")); /* checksum */ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; /* skip unused byte */ offset += 1; /* PROBE and NEIGHBORS 2 packets have capabilities flags, unused for other packets */ if (code==DVMRP_V3_PROBE || code==DVMRP_V3_NEIGHBORS_2) { static const int * capabilities[] = { &hf_cap_netmask, &hf_cap_snmp, &hf_cap_mtrace, &hf_cap_genid, &hf_cap_prune, &hf_cap_leaf, NULL }; proto_tree_add_bitmask(parent_tree, tvb, offset, hf_capabilities, ett_capabilities, capabilities, ENC_NA); } offset += 1; /* minor version */ proto_tree_add_item(parent_tree, hf_min_ver, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* major version */ proto_tree_add_item(parent_tree, hf_maj_ver, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; switch (code) { case DVMRP_V3_PROBE: /* generation id */ proto_tree_add_item(parent_tree, hf_genid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; while (tvb_reported_length_remaining(tvb, offset)>=4) { proto_tree_add_item(parent_tree, hf_neighbor, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } break; case DVMRP_V3_REPORT: offset = dissect_v3_report(tvb, parent_tree, offset); break; case DVMRP_V3_PRUNE: /* source address */ proto_tree_add_item(parent_tree, hf_saddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* group address */ proto_tree_add_item(parent_tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* prune lifetime */ proto_tree_add_item(parent_tree, hf_life, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* source netmask */ if (tvb_reported_length_remaining(tvb, offset)>=4) { proto_tree_add_item(parent_tree, hf_netmask, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } break; case DVMRP_V3_GRAFT: /* source address */ proto_tree_add_item(parent_tree, hf_saddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* group address */ proto_tree_add_item(parent_tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* source netmask */ if (tvb_reported_length_remaining(tvb, offset)>=4) { proto_tree_add_item(parent_tree, hf_netmask, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } break; case DVMRP_V3_GRAFT_ACK: /* source address */ proto_tree_add_item(parent_tree, hf_saddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* group address */ proto_tree_add_item(parent_tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* source netmask */ if (tvb_reported_length_remaining(tvb, offset)>=4) { proto_tree_add_item(parent_tree, hf_netmask, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; } break; case DVMRP_V3_ASK_NEIGHBORS: case DVMRP_V3_NEIGHBORS: /* XXX - obsolete, and the draft doesn't describe them */ break; case DVMRP_V3_ASK_NEIGHBORS_2: /* No data */ break; case DVMRP_V3_NEIGHBORS_2: while (tvb_reported_length_remaining(tvb, offset)>=12) { guint8 neighbor_count; /* local address */ proto_tree_add_item(parent_tree, hf_local, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Metric */ proto_tree_add_item(parent_tree, hf_metric, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Threshold */ proto_tree_add_item(parent_tree, hf_threshold, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Flags */ { proto_tree *tree; proto_item *item; item = proto_tree_add_item(parent_tree, hf_flags, tvb, offset, 1, ENC_NA); tree = proto_item_add_subtree(item, ett_flags); proto_tree_add_item(tree, hf_flag_tunnel, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_flag_srcroute, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_flag_down, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_flag_disabled, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_flag_querier, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_flag_leaf, tvb, offset, 1, ENC_BIG_ENDIAN); } offset += 1; /* Neighbor count */ neighbor_count = tvb_get_guint8(tvb, offset); proto_tree_add_item(parent_tree, hf_ncount, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; while ((tvb_reported_length_remaining(tvb, offset)>=4) && (neighbor_count>0)) { proto_tree_add_item(parent_tree, hf_neighbor, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; neighbor_count--; } } break; } return offset; }
static int dissect_mrdisc_mra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { guint16 num; /* Advertising Interval */ proto_tree_add_item(parent_tree, hf_advint, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* checksum */ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0); offset += 2; /* skip unused bytes */ offset += 2; /* number of options */ num = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(parent_tree, hf_numopts, tvb, offset, 2, num); offset += 2; /* process any options */ while (num--) { proto_tree *tree; proto_item *item; guint8 type,len; int old_offset = offset; item = proto_tree_add_item(parent_tree, hf_options, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_options); type = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_option, tvb, offset, 1, type); offset += 1; len = tvb_get_guint8(tvb, offset); proto_tree_add_uint(tree, hf_option_len, tvb, offset, 1, len); offset += 1; switch (type) { case MRDISC_QI: if (item) { proto_item_set_text(item,"Option: %s == %d", val_to_str(type, mrdisc_options, "unknown %x"), tvb_get_ntohs(tvb, offset)); } if (len != 2) THROW(ReportedBoundsError); proto_tree_add_item(tree, hf_qi, tvb, offset, len, ENC_BIG_ENDIAN); offset += len; break; case MRDISC_RV: if (item) { proto_item_set_text(item,"Option: %s == %d", val_to_str(type, mrdisc_options, "unknown %x"), tvb_get_ntohs(tvb, offset)); } if (len != 2) THROW(ReportedBoundsError); proto_tree_add_item(tree, hf_rv, tvb, offset, len, ENC_BIG_ENDIAN); offset += len; break; default: if (item) { proto_item_set_text(item,"Option: unknown"); } proto_tree_add_item(tree, hf_option_bytes, tvb, offset, len, ENC_NA); offset += len; } if (item) { proto_item_set_len(item, offset-old_offset); } } return offset; }