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); }
/* Code to actually dissect the packets */ static void dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures we will need to add the protocol subtree and manage it */ proto_item *ti; proto_tree *mip_tree=NULL; proto_item *tf; proto_tree *flags_tree; guint8 type; guint16 flags; gint offset=0; const guint8 *reftime; tvbuff_t *next_tvb; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MobileIP"); col_clear(pinfo->cinfo, COL_INFO); type = tvb_get_guint8(tvb, offset); switch (type) { case MIP_REGISTRATION_REQUEST: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Request: HoA=%s HA=%s CoA=%s", ip_to_str(tvb_get_ptr(tvb,4,4)), ip_to_str(tvb_get_ptr(tvb,8,4)), ip_to_str(tvb_get_ptr(tvb,12,4))); if (tree) { ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* flags */ flags = tvb_get_guint8(tvb, offset); tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 1, flags); flags_tree = proto_item_add_subtree(tf, ett_mip_flags); proto_tree_add_boolean(flags_tree, hf_mip_s, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_b, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_d, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_m, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_g, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_v, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_t, tvb, offset, 1, flags); proto_tree_add_boolean(flags_tree, hf_mip_x, tvb, offset, 1, flags); offset++; /* lifetime */ proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE); offset += 2; /* home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* home agent address */ proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE); offset += 4; /* Care of Address */ proto_tree_add_item(mip_tree, hf_mip_coa, tvb, offset, 4, FALSE); offset += 4; /* Identifier - assumed to be an NTP time here */ reftime = tvb_get_ptr(tvb, offset, 8); proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8, reftime, "Identification: %s", ntp_fmt_ts(reftime)); offset += 8; } /* if tree */ break; case MIP_REGISTRATION_REPLY: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Reply: HoA=%s HA=%s, Code=%u", ip_to_str(tvb_get_ptr(tvb,4,4)), ip_to_str(tvb_get_ptr(tvb,8,4)), tvb_get_guint8(tvb,1)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* Type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* Reply Code */ proto_tree_add_item(mip_tree, hf_mip_code, tvb, offset, 1, FALSE); offset++; /* Registration Lifetime */ proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE); offset += 2; /* Home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* Home Agent Address */ proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE); offset += 4; /* Identifier - assumed to be an NTP time here */ reftime = tvb_get_ptr(tvb, offset, 8); proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8, reftime, "Identification: %s", ntp_fmt_ts(reftime)); offset += 8; } /* if tree */ break; case MIP_NATT_TUNNEL_DATA: col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel Data: Next Header=%u", tvb_get_guint8(tvb,1)); if (tree) { /* Add Subtree */ ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* Type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* Next Header */ proto_tree_add_item(mip_tree, hf_mip_nattt_nexthdr, tvb, offset, 1, FALSE); offset++; /* reserved */ proto_tree_add_item(mip_tree, hf_mip_nattt_reserved, tvb, offset, 2, FALSE); offset += 2; } /* if tree */ else { offset += 4; } /* encapsulated payload */ next_tvb = tvb_new_subset_remaining(tvb, 4); call_dissector(ip_handle, next_tvb, pinfo, mip_tree); offset += tvb_reported_length_remaining(tvb, offset); break; case MIP_REGISTRATION_REVOCATION: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Revocation: HoA=%s HDA=%s FDA=%s", ip_to_str(tvb_get_ptr(tvb,4,4)), ip_to_str(tvb_get_ptr(tvb,8,4)), ip_to_str(tvb_get_ptr(tvb,12,4))); if (tree) { ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* reserved */ proto_tree_add_item(mip_tree, hf_mip_rev_reserved, tvb, offset, 1, FALSE); offset++; /* flags */ flags = tvb_get_ntohs(tvb, offset); tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags); flags_tree = proto_item_add_subtree(tf, ett_mip_flags); proto_tree_add_boolean(flags_tree, hf_mip_rev_a, tvb, offset, 2, flags); proto_tree_add_boolean(flags_tree, hf_mip_rev_i, tvb, offset, 2, flags); /* reserved */ proto_tree_add_uint(flags_tree, hf_mip_rev_reserved, tvb, offset, 2, flags); offset += 2; /* home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* home domain address */ proto_tree_add_item(mip_tree, hf_mip_hda, tvb, offset, 4, FALSE); offset += 4; /* foreign domain address */ proto_tree_add_item(mip_tree, hf_mip_fda, tvb, offset, 4, FALSE); offset += 4; /* revocation identifier */ proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE); offset += 4; } /* if tree */ break; case MIP_REGISTRATION_REVOCATION_ACK: col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Revocation Ack: HoA=%s", ip_to_str(tvb_get_ptr(tvb,4,4))); if (tree) { ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE); mip_tree = proto_item_add_subtree(ti, ett_mip); /* type */ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type); offset++; /* reserved */ proto_tree_add_item(mip_tree, hf_mip_ack_reserved, tvb, offset, 1, FALSE); offset++; /* flags */ flags = tvb_get_ntohs(tvb, offset); tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags); flags_tree = proto_item_add_subtree(tf, ett_mip_flags); proto_tree_add_boolean(flags_tree, hf_mip_ack_i, tvb, offset, 2, flags); /* reserved */ proto_tree_add_uint(flags_tree, hf_mip_ack_reserved, tvb, offset, 2, flags); offset += 2; /* home address */ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE); offset += 4; /* revocation identifier */ proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE); offset += 4; } /* if tree */ break; } /* End switch */ if (tree) { if (tvb_reported_length_remaining(tvb, offset) > 0) dissect_mip_extensions(tvb, offset, mip_tree); } } /* dissect_mip */