예제 #1
0
static void dissect_mqpcf_parm_int(tvbuff_t *tvb, proto_tree *tree, guint offset, guint uPrm,
                                   guint uVal, int hfindex, guint iCnt, guint iMaxCnt,
                                   guint iDigit, gboolean bParse)
{
    header_field_info *hfinfo;
    const guint8 *pVal = NULL;

    if (bParse)
        pVal = dissect_mqpcf_parm_getintval(uPrm, uVal);

    hfinfo = proto_registrar_get_nth(hfindex);

    if (iMaxCnt > 1)
    {
        if (pVal)
        {
            proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
                "%s[%*d]: %8x-(%9d)-%s", hfinfo->name, iDigit, iCnt, uVal, uVal, pVal);
        }
        else
        {
            proto_tree_add_int_format(tree, hfindex, tvb, offset, 4, uVal,
                "%s[%*d]: %8x-(%9d)", hfinfo->name, iDigit, iCnt, uVal, uVal);
        }
    }
    else
    {
        if (pVal)
        {
            proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
                "%8x-(%9d)-%s", uVal, uVal, pVal);
        }
        else
        {
            proto_tree_add_int_format_value(tree, hfindex, tvb, offset, 4, uVal,
                "%8x-(%9d)", uVal, uVal);
        }
    }
}
static void
dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *radiotap_tree = NULL;
    proto_tree *pt, *present_tree = NULL;
    proto_tree *ft;
    proto_item *ti = NULL, *hidden_item;
    int align_offset, offset;
    tvbuff_t *next_tvb;
    guint32 version;
    guint length, length_remaining;
    guint32 rate, freq, flags;
    gint8 dbm;
    guint8 db, rflags;
    guint32 present, next_present;
    int bit;
    /* backward compat with bit 14 == fcs in header */
    proto_item *hdr_fcs_ti = NULL;
    int hdr_fcs_offset = 0;
    guint32 sent_fcs = 0;
    guint32 calc_fcs;

    struct _radiotap_info *radiotap_info;
    static struct _radiotap_info rtp_info_arr[1];
    
    radiotap_info = &rtp_info_arr[0];

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
    col_clear(pinfo->cinfo, COL_INFO);
    offset = 0;

    version = tvb_get_guint8(tvb, offset);
    length = tvb_get_letohs(tvb, offset+2);
    present = tvb_get_letohl(tvb, offset+4);
    
    radiotap_info->radiotap_length = length;

    col_add_fstr(pinfo->cinfo, COL_INFO, "Radiotap Capture v%u, Length %u",
		version, length);

    /* Dissect the packet */
    if (tree) {
	ti = proto_tree_add_protocol_format(tree, proto_radiotap,
		tvb, 0, length, "Radiotap Header v%u, Length %u", version, length);
	radiotap_tree = proto_item_add_subtree(ti, ett_radiotap);
	proto_tree_add_uint(radiotap_tree, hf_radiotap_version,
		tvb, offset, 1, version);
	proto_tree_add_item(radiotap_tree, hf_radiotap_pad,
		tvb, offset + 1, 1, FALSE);
	ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_length,
		tvb, offset + 2, 2, length);
    }
    length_remaining = length;

    /*
     * FIXME: This only works if there is exactly 1 it_present
     *        field in the header
     */
    if (length_remaining < RADIOTAP_MIN_HEADER_LEN) {
	/*
	 * Radiotap header is shorter than the fixed-length portion
	 * plus one "present" bitset.
	 */
	if (tree)
	    proto_item_append_text(ti, " (bogus - minimum length is 8)");
	return;
    }
    /* Subtree for the "present flags" bitfield. */
    if (tree) {
	pt = proto_tree_add_uint(radiotap_tree, hf_radiotap_present,
	    tvb, offset + 4, 4, present);
	present_tree = proto_item_add_subtree(pt, ett_radiotap_present);

	proto_tree_add_item(present_tree, hf_radiotap_present_tsft,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_flags,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_rate,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_channel,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_fhss,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antsignal,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antnoise,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_lock_quality,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_tx_attenuation,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_db_tx_attenuation,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_dbm_tx_attenuation,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_antenna,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_db_antsignal,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_db_antnoise,
	    tvb, offset + 4, 4, TRUE);
	if (radiotap_bit14_fcs) {
		proto_tree_add_item(present_tree, hf_radiotap_present_hdrfcs,
			tvb, offset + 4, 4, TRUE);
	} else {
		proto_tree_add_item(present_tree, hf_radiotap_present_rxflags,
			tvb, offset + 4, 4, TRUE);
	}
	proto_tree_add_item(present_tree, hf_radiotap_present_xchannel,
	    tvb, offset + 4, 4, TRUE);
	proto_tree_add_item(present_tree, hf_radiotap_present_ext,
	    tvb, offset + 4, 4, TRUE);
    }
    offset += RADIOTAP_MIN_HEADER_LEN;
    length_remaining -= RADIOTAP_MIN_HEADER_LEN;

    rflags = 0;
    for (; present; present = next_present) {
	/* clear the least significant bit that is set */
	next_present = present & (present - 1);

	/* extract the least significant bit that is set */
	bit = BITNO_32(present ^ next_present);

	switch (bit) {

	case IEEE80211_RADIOTAP_TSFT:
	    align_offset = ALIGN_OFFSET(offset, 8);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 8)
		break;
            radiotap_info->tsft=tvb_get_letoh64(tvb, offset);
	    if (tree) {
		proto_tree_add_uint64(radiotap_tree, hf_radiotap_mactime,
				tvb, offset, 8,radiotap_info->tsft );
	    }
	    offset+=8;
	    length_remaining-=8;
	    break;

	case IEEE80211_RADIOTAP_FLAGS:
	{
	    proto_tree *flags_tree;
	    if (length_remaining < 1)
		break;
	    rflags = tvb_get_guint8(tvb, offset);
	    if (tree) {
		ft = proto_tree_add_item(radiotap_tree, hf_radiotap_flags,
					 tvb, offset, 1, FALSE);
		flags_tree = proto_item_add_subtree(ft, ett_radiotap_flags);

		proto_tree_add_item(flags_tree, hf_radiotap_flags_cfp,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_preamble,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_wep,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_frag,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_fcs,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_datapad,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_badfcs,
			tvb, offset, 1, FALSE);
		proto_tree_add_item(flags_tree, hf_radiotap_flags_shortgi,
			tvb, offset, 1, FALSE);
	    }
	    offset++;
	    length_remaining--;
	    break;
	}

	case IEEE80211_RADIOTAP_RATE:
	    if (length_remaining < 1)
		break;
	    rate = tvb_get_guint8(tvb, offset);
	    if (rate & 0x80) {
		/* XXX adjust by CW and short GI like other sniffers? */
		rate = ieee80211_htrates[rate & 0xf];
	    }
	    col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%d.%d",
		rate / 2, rate & 1 ? 5 : 0);
	    if (tree) {
		proto_tree_add_float_format(radiotap_tree, hf_radiotap_datarate,
			tvb, offset, 1, (float)rate / 2,
			"Data Rate: %.1f Mb/s", (float)rate / 2);
	    }
	    offset++;
	    length_remaining--;
            radiotap_info->rate = rate;
	    break;

	case IEEE80211_RADIOTAP_CHANNEL:
	{
	    proto_item *it;
	    proto_tree *flags_tree;
	    gchar *chan_str;

	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    if (tree) {
		freq = tvb_get_letohs(tvb, offset);
		flags = tvb_get_letohs(tvb, offset+2);
		chan_str = ieee80211_mhz_to_str(freq);
		col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%s", chan_str);
		proto_tree_add_uint_format(radiotap_tree, hf_radiotap_channel_frequency,
				tvb, offset, 2, freq,
				"Channel frequency: %s", chan_str);
		g_free(chan_str);
		/* We're already 2-byte aligned. */
		it = proto_tree_add_uint(radiotap_tree, hf_radiotap_channel_flags,
			tvb, offset+2, 2, flags);
		flags_tree = proto_item_add_subtree(it, ett_radiotap_channel_flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_turbo,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_cck,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_ofdm,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_2ghz,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_5ghz,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_passive,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_dynamic,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_gfsk,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_gsm,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_sturbo,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_half,
			tvb, offset+3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_quarter,
			tvb, offset+3, 1, flags);
		radiotap_info->freq=freq;
		radiotap_info->flags=flags;
	    }
	    offset+=4 /* Channel + flags */;
	    length_remaining-=4;
	    break;
	}

	case IEEE80211_RADIOTAP_FHSS:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_hopset,
		tvb, offset, 1, FALSE);
	    proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_pattern,
		tvb, offset, 1, FALSE);
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
	    if (length_remaining < 1)
		break;
	    dbm = (gint8) tvb_get_guint8(tvb, offset);
	    col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", dbm);
	    if (tree) {
		proto_tree_add_int_format(radiotap_tree,
					  hf_radiotap_dbm_antsignal,
					  tvb, offset, 1, dbm,
					  "SSI Signal: %d dBm", dbm);
	    }
	    offset++;
	    length_remaining--;
            radiotap_info->dbm_antsignal=dbm;
	    break;

	case IEEE80211_RADIOTAP_DBM_ANTNOISE:
	    if (length_remaining < 1)
		break;
	    dbm = (gint8) tvb_get_guint8(tvb, offset);
	    if (tree) {
		proto_tree_add_int_format(radiotap_tree,
					  hf_radiotap_dbm_antnoise,
					  tvb, offset, 1, dbm,
					  "SSI Noise: %d dBm", dbm);
	    }
	    offset++;
	    length_remaining--;
            radiotap_info->dbm_antnoise=dbm;
	    break;

	case IEEE80211_RADIOTAP_LOCK_QUALITY:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    if (tree) {
		proto_tree_add_uint(radiotap_tree, hf_radiotap_quality,
				tvb, offset, 2, tvb_get_letohs(tvb, offset));
	    }
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_TX_ATTENUATION:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    proto_tree_add_item(radiotap_tree, hf_radiotap_tx_attenuation,
		tvb, offset, 2, FALSE);
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
	    align_offset = ALIGN_OFFSET(offset, 2);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 2)
		break;
	    proto_tree_add_item(radiotap_tree, hf_radiotap_db_tx_attenuation,
		tvb, offset, 2, FALSE);
	    offset+=2;
	    length_remaining-=2;
	    break;

	case IEEE80211_RADIOTAP_DBM_TX_POWER:
	    if (length_remaining < 1)
		break;
	    if (tree) {
		proto_tree_add_int(radiotap_tree, hf_radiotap_txpower,
				   tvb, offset, 1, tvb_get_guint8(tvb, offset));
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_ANTENNA:
	    if (length_remaining < 1)
		break;
	    if (tree) {
		proto_tree_add_uint(radiotap_tree, hf_radiotap_antenna,
				   tvb, offset, 1, tvb_get_guint8(tvb, offset));
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
	    if (length_remaining < 1)
		break;
	    db = tvb_get_guint8(tvb, offset);
	    col_add_fstr(pinfo->cinfo, COL_RSSI, "%u dB", db);
	    if (tree) {
		proto_tree_add_uint_format(radiotap_tree,
					   hf_radiotap_db_antsignal,
					   tvb, offset, 1, db,
					   "SSI Signal: %u dB", db);
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_DB_ANTNOISE:
	    if (length_remaining < 1)
		break;
	    db = tvb_get_guint8(tvb, offset);
	    if (tree) {
		proto_tree_add_uint_format(radiotap_tree,
					   hf_radiotap_db_antnoise,
					   tvb, offset, 1, db,
					   "SSI Noise: %u dB", db);
	    }
	    offset++;
	    length_remaining--;
	    break;

	case IEEE80211_RADIOTAP_RX_FLAGS:
	{
	    proto_tree *flags_tree;
	    if (radiotap_bit14_fcs) {
	        align_offset = ALIGN_OFFSET(offset, 4);
	        offset += align_offset;
	        length_remaining -= align_offset;
	        if (length_remaining < 4)
	            break;
                if (tree) {
                    sent_fcs = tvb_get_ntohl(tvb, offset);
                    hdr_fcs_ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_fcs,
                                                     tvb, offset, 4, sent_fcs);
                    hdr_fcs_offset = offset;
                }
                offset+=4;
                length_remaining-=4;
	    } else {
	        proto_item *it;

                align_offset = ALIGN_OFFSET(offset, 2);
                offset += align_offset;
                length_remaining -= align_offset;
                if (length_remaining < 2)
                    break;
                if (tree) {
                    flags = tvb_get_letohs(tvb, offset);
                    it = proto_tree_add_uint(radiotap_tree, hf_radiotap_rxflags,
                            tvb, offset, 2, flags);
                    flags_tree = proto_item_add_subtree(it, ett_radiotap_rxflags);
                    proto_tree_add_boolean(flags_tree, hf_radiotap_rxflags_badplcp,
                            tvb, offset, 1, flags);
                }
                offset+=2;
                length_remaining-=2;
            }
	    break;
	}

	case IEEE80211_RADIOTAP_XCHANNEL:
	{
	    proto_item *it;
	    proto_tree *flags_tree;

	    align_offset = ALIGN_OFFSET(offset, 4);
	    offset += align_offset;
	    length_remaining -= align_offset;
	    if (length_remaining < 8)
		break;
	    if (tree) {
	        int channel;
	        guint8 maxpower;

		flags = tvb_get_letohl(tvb, offset);
		freq = tvb_get_letohs(tvb, offset+4);
		channel = tvb_get_guint8(tvb, offset+6);
		maxpower = tvb_get_guint8(tvb, offset+7);
		proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel,
			tvb, offset+6, 1, (guint32) channel);
		proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_frequency,
			tvb, offset+4, 2, freq);
		it = proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_flags,
			tvb, offset+0, 4, flags);
		flags_tree = proto_item_add_subtree(it, ett_radiotap_xchannel_flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_turbo,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_cck,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ofdm,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_2ghz,
			tvb, offset+0, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_5ghz,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_passive,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_dynamic,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_gfsk,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_gsm,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_sturbo,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_half,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_quarter,
			tvb, offset+1, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht20,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht40u,
			tvb, offset+2, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht40d,
			tvb, offset+2, 1, flags);
#if 0
		proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_maxpower,
			tvb, offset+7, 1, maxpower);
#endif
	    }
	    offset+=8 /* flags + freq + ieee + maxregpower */;
	    length_remaining-=8;
	    break;
	}

	default:
	    /*
	     * This indicates a field whose size we do not
	     * know, so we cannot proceed.
	     */
	    next_present = 0;
	    continue;
	}
    }

    /* This handles the case of an FCS exiting at the end of the frame. */
    if (rflags & IEEE80211_RADIOTAP_F_FCS)
	pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
    else
	pinfo->pseudo_header->ieee_802_11.fcs_len = 0;

    /* Grab the rest of the frame. */
    next_tvb = tvb_new_subset_remaining(tvb, length);

    /* If we had an in-header FCS, check it.
     * This can only happen if the backward-compat configuration option
     * is chosen by the user. */
    if (hdr_fcs_ti) {
        /* It would be very strange for the header to have an FCS for the
         * frame *and* the frame to have the FCS at the end, but it's possible, so
         * take that into account by using the FCS length recorded in pinfo. */

        /* Watch out for [erroneously] short frames */
        if (tvb_length(next_tvb) > (unsigned int) pinfo->pseudo_header->ieee_802_11.fcs_len) {
            calc_fcs = crc32_802_tvb(next_tvb,
                    tvb_length(next_tvb) - pinfo->pseudo_header->ieee_802_11.fcs_len);

            /* By virtue of hdr_fcs_ti being set, we know that 'tree' is set,
             * so there's no need to check it here. */
            if (calc_fcs == sent_fcs) {
                proto_item_append_text(hdr_fcs_ti, " [correct]");
            }
            else {
                proto_item_append_text(hdr_fcs_ti,
                        " [incorrect, should be 0x%08x]", calc_fcs);
                hidden_item = proto_tree_add_boolean(radiotap_tree, hf_radiotap_fcs_bad,
                        tvb, hdr_fcs_offset, 4, TRUE);
                PROTO_ITEM_SET_HIDDEN(hidden_item);
            }
        }
        else {
                proto_item_append_text(hdr_fcs_ti,
                        " [cannot verify - not enough data]");
        }
    }

    /* dissect the 802.11 header next */
    call_dissector((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ?
        ieee80211_datapad_handle : ieee80211_handle,
        next_tvb, pinfo, tree);
    
    tap_queue_packet(radiotap_tap, pinfo, radiotap_info);
}
예제 #3
0
static void
dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
{
	proto_tree      *flags_tree;
	proto_item	*tf;
	guint8		stratum;
	guint8		ppoll;
	gint8		precision;
	double		rootdelay;
	double		rootdispersion;
	const guint8	*refid;
	guint32		refid_addr;
	const guint8	*reftime;
	const guint8	*org;
	const guint8	*rec;
	const guint8	*xmt;
	const gchar	*buffc;
	gchar		*buff;
	int		i;
	int		macofs;
	gint            maclen;

	tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);

	/* Adding flag subtree and items */
	flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
	proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
	proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
	proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);

	/* Stratum, 1byte field represents distance from primary source
	 */
	stratum = tvb_get_guint8(tvb, 1);
	if (stratum == 0) {
		buffc="Peer Clock Stratum: unspecified or unavailable (%u)";
	} else if (stratum == 1) {
		buffc="Peer Clock Stratum: primary reference (%u)";
	} else if ((stratum >= 2) && (stratum <= 15)) {
		buffc="Peer Clock Stratum: secondary reference (%u)";
	} else {
		buffc="Peer Clock Stratum: reserved: %u";
	}
	proto_tree_add_uint_format(ntp_tree, hf_ntp_stratum, tvb, 1, 1,
				   stratum, buffc, stratum);
	/* Poll interval, 1byte field indicating the maximum interval
	 * between successive messages, in seconds to the nearest
	 * power of two.
	 */
	ppoll = tvb_get_guint8(tvb, 2);
	if ((ppoll >= 4) && (ppoll <= 17)) {
		proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
				   ppoll, 
				   "Peer Polling Interval: %u (%u sec)",
				   ppoll,
				   1 << ppoll);
	} else {
		proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
				   ppoll,
				   "Peer Polling Interval: invalid (%u)",
				   ppoll);
	}
	
	/* Precision, 1byte field indicating the precision of the
	 * local clock, in seconds to the nearest power of two.
	 */
	precision = tvb_get_guint8(tvb, 3);
	proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
				   precision,
				   "Peer Clock Precision: %8.6f sec",
				   pow(2, precision));

	/* Root Delay is a 32-bit signed fixed-point number indicating
	 * the total roundtrip delay to the primary reference source,
	 * in seconds with fraction point between bits 15 and 16.
	 */
	rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
			(tvb_get_ntohs(tvb, 6) / 65536.0);
	proto_tree_add_double_format(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
				   rootdelay,
				   "Root Delay: %9.4f sec",
				   rootdelay);

	/* Root Dispersion, 32-bit unsigned fixed-point number indicating
	 * the nominal error relative to the primary reference source, in
	 * seconds with fraction point between bits 15 and 16.
	 */
	rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
				(tvb_get_ntohs(tvb, 10) / 65536.0);
	proto_tree_add_double_format(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
				   rootdispersion,
				   "Root Dispersion: %9.4f sec",
				   rootdispersion);

	/* Now, there is a problem with secondary servers.  Standards
	 * asks from stratum-2 - stratum-15 servers to set this to the
	 * low order 32 bits of the latest transmit timestamp of the
	 * reference source.
	 * But, all V3 and V4 servers set this to IP adress of their
	 * higher level server. My decision was to resolve this address.
	 */
	refid = tvb_get_ptr(tvb, 12, 4);
	buff = ep_alloc(NTP_TS_SIZE);
	if (stratum <= 1) {
		g_snprintf (buff, NTP_TS_SIZE, "Unidentified reference source '%.4s'",
			refid);
		for (i = 0; primary_sources[i].id; i++) {
			if (memcmp (refid, primary_sources[i].id, 4) == 0) {
				g_snprintf(buff, NTP_TS_SIZE, "%s",
					primary_sources[i].data);
				break;
			}
		}
	} else {
		int buffpos;
		refid_addr = tvb_get_ipv4(tvb, 12);
		buffpos = g_snprintf(buff, NTP_TS_SIZE, "%s", get_hostname (refid_addr));
		if (buffpos >= NTP_TS_SIZE) {
			buff[NTP_TS_SIZE-4]='.';
			buff[NTP_TS_SIZE-3]='.';
			buff[NTP_TS_SIZE-2]='.';
			buff[NTP_TS_SIZE-1]=0;
		}
	}
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
				   refid,
				   "Reference Clock ID: %s", buff);

	/* Reference Timestamp: This is the time at which the local clock was
	 * last set or corrected.
	 */
	reftime = tvb_get_ptr(tvb, 16, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
				   reftime,
			           "Reference Clock Update Time: %s",
				   ntp_fmt_ts(reftime));

	/* Originate Timestamp: This is the time at which the request departed
	 * the client for the server.
	 */
	org = tvb_get_ptr(tvb, 24, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
				   org,
			           "Originate Time Stamp: %s",
				   ntp_fmt_ts(org));

	/* Receive Timestamp: This is the time at which the request arrived at
	 * the server.
	 */
	rec = tvb_get_ptr(tvb, 32, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
				   rec,
			           "Receive Time Stamp: %s",
				   ntp_fmt_ts(rec));

	/* Transmit Timestamp: This is the time at which the reply departed the
	 * server for the client.
	 */
	xmt = tvb_get_ptr(tvb, 40, 8);
	proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
				   xmt,
			           "Transmit Time Stamp: %s",
				   ntp_fmt_ts(xmt));

	/* MAX_MAC_LEN is the largest message authentication code
	 * (MAC) length.  If we have more data left in the packet
	 * after the header than that, the extra data is NTP4
	 * extensions; parse them as such.
	 */
	macofs = 48;
	while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
		macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);

	/* When the NTP authentication scheme is implemented, the
	 * Key Identifier and Message Digest fields contain the
	 * message authentication code (MAC) information defined in
	 * Appendix C of RFC-1305. Will print this as hex code for now.
	 */
	if (tvb_reported_length_remaining(tvb, macofs) >= 4)
		proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
				    FALSE);
	macofs += 4;
	maclen = tvb_reported_length_remaining(tvb, macofs);
	if (maclen > 0)
		proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
				    maclen, FALSE);
}