diff options
author | Anders Broman <anders.broman@ericsson.com> | 2005-10-11 05:23:27 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2005-10-11 05:23:27 +0000 |
commit | b854132495bdfd91fe2975aa1dfff0e9874e01fd (patch) | |
tree | 7cfce27e5f299f55b94cb948c07e3cf8ec75de0d | |
parent | 24df5c368e69b905137e22a94f941949547d7736 (diff) |
From Hannes Gredler:
fixes the AF/SAFI codepoints
for BGP Layer-2 VPNs from a Juniper pre-standard implementation to the new "official" IANA assigned codepoints.
From Julian Onions
packet-rmt-norm.ch Decode more oif the protocol
svn path=/trunk/; revision=16183
-rw-r--r-- | epan/dissectors/packet-bgp.c | 37 | ||||
-rw-r--r-- | epan/dissectors/packet-bgp.h | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-norm.c | 663 | ||||
-rw-r--r-- | epan/dissectors/packet-rmt-norm.h | 114 |
4 files changed, 722 insertions, 93 deletions
diff --git a/epan/dissectors/packet-bgp.c b/epan/dissectors/packet-bgp.c index 36315b8500..fe7cdcdd6e 100644 --- a/epan/dissectors/packet-bgp.c +++ b/epan/dissectors/packet-bgp.c @@ -244,6 +244,7 @@ static const value_string bgpattr_nlri_safi[] = { { SAFNUM_UNIMULC, "Unicast+Multicast" }, { SAFNUM_MPLS_LABEL, "Labeled Unicast"}, { SAFNUM_TUNNEL, "Tunnel"}, + { SAFNUM_VPLS, "VPLS"}, { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" }, /* draft-rosen-rfc2547bis-03 */ { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" }, { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" }, @@ -611,10 +612,12 @@ mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *buf, } break; case AFNUM_L2VPN: + case AFNUM_L2VPN_OLD: switch (safi) { case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */ case SAFNUM_LAB_VPNMULCAST: case SAFNUM_LAB_VPNUNIMULC: + case SAFNUM_VPLS: length = 4; /* the next-hop is simply an ipv4 addr */ ip4addr = tvb_get_ipv4(tvb, offset + 0); strptr += g_snprintf(strptr, buf_len-(strptr-buf), "IPv4=%s", @@ -1008,11 +1011,13 @@ decode_prefix_MP(proto_tree *tree, int hf_addr4, int hf_addr6, break; case AFNUM_L2VPN: + case AFNUM_L2VPN_OLD: switch (safi) { case SAFNUM_LAB_VPNUNICAST: case SAFNUM_LAB_VPNMULCAST: case SAFNUM_LAB_VPNUNIMULC: + case SAFNUM_VPLS: plen = tvb_get_ntohs(tvb,offset); rd_type=tvb_get_ntohs(tvb,offset+2); ce_id=tvb_get_ntohs(tvb,offset+10); @@ -2078,29 +2083,39 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree) "Next hop network address (%d %s)", nexthop_len, plurality(nexthop_len, "byte", "bytes")); subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna); - if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) { - /* - * The addresses don't contain lengths, so if we - * don't understand the address family type, we - * cannot parse the subsequent addresses as we - * don't know how long they are. - */ + + /* + * The addresses don't contain lengths, so if we + * don't understand the address family type, we + * cannot parse the subsequent addresses as we + * don't know how long they are. + */ + switch (af) { + default: proto_tree_add_text(subtree3, tvb, o + i + aoff + 4, nexthop_len, "Unknown Address Family"); - } else { + break; + + case AFNUM_INET: + case AFNUM_INET6: + case AFNUM_L2VPN: + case AFNUM_L2VPN_OLD: + j = 0; while (j < nexthop_len) { advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j, - junk_gbuf, MAX_STR_LEN) ; + junk_gbuf, MAX_STR_LEN) ; if (advance == 0) /* catch if this is a unknown AFI type*/ - break; + break; if (j + advance > nexthop_len) break; proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j, advance, "Next hop: %s (%u)", junk_gbuf, advance); j += advance; } - } + break; + } + tlen -= nexthop_len + 4; aoff += nexthop_len + 4 ; diff --git a/epan/dissectors/packet-bgp.h b/epan/dissectors/packet-bgp.h index 4c9a037b38..0b59ab5b5c 100644 --- a/epan/dissectors/packet-bgp.h +++ b/epan/dissectors/packet-bgp.h @@ -201,6 +201,7 @@ struct bgp_attr { #define SAFNUM_UNIMULC 3 #define SAFNUM_MPLS_LABEL 4 /* rfc3107 */ #define SAFNUM_TUNNEL 64 /* draft-nalawade-kapoor-tunnel-safi-02.txt */ +#define SAFNUM_VPLS 65 #define SAFNUM_LAB_VPNUNICAST 128 /* Draft-rosen-rfc2547bis-03 */ #define SAFNUM_LAB_VPNMULCAST 129 #define SAFNUM_LAB_VPNUNIMULC 130 diff --git a/epan/dissectors/packet-rmt-norm.c b/epan/dissectors/packet-rmt-norm.c index 0b09b437b1..33554c8ee6 100644 --- a/epan/dissectors/packet-rmt-norm.c +++ b/epan/dissectors/packet-rmt-norm.c @@ -3,6 +3,8 @@ * NORM Protocol Instantiation dissector * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net> * + * Extensive changes to decode more information Julian Onions + * * Negative-acknowledgment (NACK)-Oriented Reliable Multicast (NORM): * ------------------------------------------------------------------ * @@ -26,12 +28,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -49,21 +51,52 @@ #include <epan/packet.h> #include <epan/prefs.h> +#include <epan/strutil.h> #include "packet-rmt-norm.h" +#include <math.h> /* String tables */ -const value_string string_norm_type[] = +static const value_string string_norm_type[] = +{ + { NORM_INFO, "INFO" }, + { NORM_DATA, "DATA" }, + { NORM_CMD, "CMD" }, + { NORM_NACK, "NACK" }, + { NORM_ACK, "ACK" }, + { NORM_REPORT, "REPORT" }, + { 0, NULL } +}; + +static const value_string string_norm_cmd_type[] = { - { 1, "NORM_INFO" }, - { 2, "NORM_DATA" }, - { 3, "NORM_CMD" }, - { 4, "NORM_NACK" }, - { 5, "NORM_ACK" }, - { 6, "NORM_REPORT" }, + { NORM_CMD_FLUSH, "FLUSH" }, + { NORM_CMD_EOT, "EOT" }, + { NORM_CMD_SQUELCH, "SQUELCH" }, + { NORM_CMD_CC, "CC" }, + { NORM_CMD_REPAIR_ADV, "REPAIR_ADV" }, + { NORM_CMD_ACK_REQ, "ACK_REQ" }, + { NORM_CMD_APPLICATION, "APPLICATION" }, { 0, NULL } }; +static const value_string string_norm_ack_type[] = +{ + { NORM_ACK_CC, "ACK CC" }, + { NORM_ACK_FLUSH, "ACK FLUSH" }, + { 0, NULL } +}; + +static const value_string string_norm_nack_form[] = +{ + { NORM_NACK_ITEMS, "Items" }, + { NORM_NACK_RANGES, "Ranges" }, + { NORM_NACK_ERASURES, "Erasures" }, + { 0, NULL } +}; + +#define hdrlen2bytes(x) ((x)*4U) + /* Initialize the protocol and registered fields */ /* ============================================= */ @@ -97,6 +130,393 @@ static void norm_prefs_save(struct _norm_prefs *p, struct _norm_prefs *p_old) *p_old = *p; } +static const double RTT_MIN = 1.0e-06; +static const double RTT_MAX = 1000; + +static double UnquantizeRtt(unsigned char qrtt) +{ + return ((qrtt <= 31) ? (((double)(qrtt+1))*(double)RTT_MIN) : + (RTT_MAX/exp(((double)(255-qrtt))/(double)13.0))); +} + +static double UnquantizeGSize(guint8 gsize) +{ + guint mant = (gsize & 0x8) ? 5 : 1; + guint exponent = gsize & 0x7; + exponent ++; + return mant * pow(10, exponent); +} + +static double UnquantizeSendRate(guint16 send_rate) +{ + return (send_rate >> 4) * 10.0 / 4096.0 * pow(10.0, (send_rate & 0x000f)); +} + +/* code to dissect fairly common sequence in NORM packets */ +static guint dissect_grrtetc(proto_tree *tree, tvbuff_t *tvb, guint offset) +{ + guint8 backoff; + double gsize; + double grtt; + proto_tree_add_item(tree, hf.instance_id, tvb, offset, 2, FALSE); offset+=2; + grtt = UnquantizeRtt(tvb_get_guint8(tvb, offset)); + proto_tree_add_double(tree, hf.grtt, tvb, offset, 1, grtt); offset++; + backoff = hi_nibble(tvb_get_guint8(tvb, offset)); + gsize = UnquantizeGSize((guint8)lo_nibble(tvb_get_guint8(tvb, offset))); + proto_tree_add_uint(tree, hf.backoff, tvb, offset, 1, backoff); + proto_tree_add_double(tree, hf.gsize, tvb, offset, 1, gsize); + offset++; + return offset; +} + +/* split out some common FEC handling */ +static guint dissect_feccode(struct _norm *norm, struct _fec_ptr *f, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo, gint reserved) +{ + f->fec = &norm->fec; + f->hf = &hf.fec; + f->ett = &ett.fec; + f->prefs = &preferences.fec; + + + norm->fec.encoding_id = tvb_get_guint8(tvb, offset); + norm->fec.encoding_id_present = 1; + proto_tree_add_item(tree, hf.fec.encoding_id, tvb, offset, 1, FALSE); offset++; + if (reserved) { + proto_tree_add_item(tree, hf.reserved, tvb, offset, 1, FALSE); offset++; + } + proto_tree_add_item(tree, hf.object_transport_id, tvb, offset, 2, FALSE); offset+=2; + + if (norm->fec.encoding_id_present && tvb_length(tvb) > offset) { + fec_dissector(*f, tvb, tree, &offset); + if (check_col(pinfo->cinfo, COL_INFO)) + fec_info_column(f->fec, pinfo); + } + return offset; +} + +static guint dissect_norm_hdrext(struct _norm *norm, struct _fec_ptr *f, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + guint i; + proto_item *ti; + /* Allocate an array of _ext elements */ + GArray *ext; + guint offset_old = offset; + proto_tree *ext_tree; + + ext = g_array_new(FALSE, TRUE, sizeof(struct _ext)); + + rmt_ext_parse(ext, tvb, &offset, hdrlen2bytes(norm->hlen)); + + if (ext->len > 0) + { + if (tree) + { + /* Add the extensions subtree */ + ti = proto_tree_add_uint(tree, hf.extension, + tvb, offset_old, + offset - offset_old, ext->len); + ext_tree = proto_item_add_subtree(ti, ett.hdrext); + } else + ext_tree = NULL; + + /* Add the extensions to the subtree */ + for (i = 0; i < ext->len; i++) + fec_decode_ext_fti(&g_array_index(ext, struct _ext, i), + tvb, ext_tree, ett.hdrext, *f); + } + g_array_free(ext, TRUE); + return offset; +} + +/* code to dissect NORM data packets */ +static void dissect_norm_data(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + guint8 flags; + proto_item *ti; + proto_tree *flag_tree; + struct _fec_ptr f; + + offset = dissect_grrtetc(tree, tvb, offset); + + + ti = proto_tree_add_item(tree, hf.flags, tvb, offset, 1, FALSE); + flags = tvb_get_guint8(tvb, offset); + flag_tree = proto_item_add_subtree(ti, ett.flags); + proto_tree_add_item(flag_tree, hf.flag.repair, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.explicit, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.info, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.unreliable, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.file, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.stream, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.msgstart, tvb, offset, 1, FALSE); + offset++; + + offset = dissect_feccode(norm, &f, tree, tvb, offset, pinfo, 0); + + if (offset < hdrlen2bytes(norm->hlen)) { + offset = dissect_norm_hdrext(norm, &f, tree, tvb, offset, pinfo); + } + if (flags & NORM_FLAG_STREAM) { + ti = proto_tree_add_text(tree, tvb, offset, 8, "Stream Data"); + flag_tree = proto_item_add_subtree(ti, ett.streampayload); + proto_tree_add_item(flag_tree, hf.reserved, tvb, offset, 2, FALSE); offset+=2; + proto_tree_add_item(flag_tree, hf.payload_len, tvb, offset, 2, FALSE); offset+=2; + proto_tree_add_item(flag_tree, hf.payload_offset, tvb, offset, 4, FALSE); offset+=4; + + } + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); + +} + +/* code to dissect NORM info packets */ +static void dissect_norm_info(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + guint8 flags; + proto_item *ti; + proto_tree *flag_tree; + + offset = dissect_grrtetc(tree, tvb, offset); + + ti = proto_tree_add_item(tree, hf.flags, tvb, offset, 1, FALSE); + flags = tvb_get_guint8(tvb, offset); + flag_tree = proto_item_add_subtree(ti, ett.flags); + proto_tree_add_item(flag_tree, hf.flag.repair, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.explicit, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.info, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.unreliable, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.file, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.stream, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.flag.msgstart, tvb, offset, 1, FALSE); + offset++; + + proto_tree_add_item(tree, hf.fec.encoding_id, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(tree, hf.object_transport_id, tvb, offset, 2, FALSE); offset+=2; + + if (offset < hdrlen2bytes(norm->hlen)) { + struct _fec_ptr f; + memset(&f, 0, sizeof f); + f.fec = &norm->fec; + f.hf = &hf.fec; + f.ett = &ett.fec; + f.prefs = &preferences.fec; + offset = dissect_norm_hdrext(norm, &f, tree, tvb, offset, pinfo); + } + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); + +} +/* code to dissect NORM cmd(flush) packets */ +static guint dissect_norm_cmd_flush(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + struct _fec_ptr f; + offset = dissect_feccode(norm, &f, tree, tvb, offset, pinfo, 0); + if (offset < hdrlen2bytes(norm->hlen)) { + offset = dissect_norm_hdrext(norm, &f, tree, tvb, offset, pinfo); + } + return offset; +} + +/* code to dissect NORM cmd(flush) packets */ +static guint dissect_norm_cmd_repairadv(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + proto_tree_add_item(tree, hf.flags, tvb, offset, 1, FALSE); offset ++; + proto_tree_add_item(tree, hf.reserved, tvb, offset, 2, FALSE); offset +=2; + + if (offset < hdrlen2bytes(norm->hlen)) { + struct _fec_ptr f; + memset(&f, 0, sizeof f); + f.fec = &norm->fec; + f.hf = &hf.fec; + f.ett = &ett.fec; + f.prefs = &preferences.fec; + offset = dissect_norm_hdrext(norm, &f, tree, tvb, offset, pinfo); + } + return offset; +} + +/* code to dissect NORM cmd(cc) packets */ +static guint dissect_norm_cmd_cc(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + proto_tree_add_item(tree, hf.reserved, tvb, offset, 1, FALSE); offset ++; + proto_tree_add_item(tree, hf.cc_sequence, tvb, offset, 2, FALSE); offset += 2; + + proto_tree_add_item(tree, hf.cc_sts, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(tree, hf.cc_stus, tvb, offset, 4, FALSE); offset += 4; + if (offset < hdrlen2bytes(norm->hlen)) { + struct _fec_ptr f; + memset(&f, 0, sizeof f); + f.fec = &norm->fec; + f.hf = &hf.fec; + f.ett = &ett.fec; + f.prefs = &preferences.fec; + offset = dissect_norm_hdrext(norm, &f, tree, tvb, offset, pinfo); + } + while (offset + 8 <= tvb_length(tvb)) { + proto_item *ti, *tif; + proto_tree *cc_tree, *flag_tree; + double grtt; + ti = proto_tree_add_text(tree, tvb, offset, 8, "Congestion Control"); + cc_tree = proto_item_add_subtree(ti, ett.congestioncontrol); + proto_tree_add_item(cc_tree, hf.cc_node_id, tvb, offset, 4, FALSE); offset += 4; + tif = proto_tree_add_item(cc_tree, hf.cc_flags, tvb, offset, 1, FALSE); + flag_tree = proto_item_add_subtree(tif, ett.flags); + proto_tree_add_item(flag_tree, hf.cc_flags_clr, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.cc_flags_plr, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.cc_flags_rtt, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.cc_flags_start, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.cc_flags_leave, tvb, offset, 1, FALSE); + offset += 1; + grtt = UnquantizeRtt(tvb_get_guint8(tvb, offset)); + proto_tree_add_double(cc_tree, hf.cc_rtt, tvb, offset, 1, grtt); offset += 1; + grtt = UnquantizeSendRate(tvb_get_ntohs(tvb, offset)); + proto_tree_add_double(cc_tree, hf.cc_rate, tvb, offset, 2, grtt); offset += 2; + } + return offset; +} + +/* code to dissect NORM cmd(squelch) packets */ +static guint dissect_norm_cmd_squelch(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + struct _fec_ptr f; + offset = dissect_feccode(norm, &f, tree, tvb, offset, pinfo, 0); + + while (offset + 2 <= tvb_length(tvb)) { + proto_tree_add_item(tree, hf.cc_transport_id, tvb, offset, 4, FALSE); offset += 2; + } + return offset; +} + +/* code to dissect NORM cmd(squelch) packets */ +static guint dissect_norm_cmd_ackreq(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + proto_tree_add_item(tree, hf.reserved, tvb, offset, 1, FALSE); offset ++; + proto_tree_add_item(tree, hf.ack_type, tvb, offset, 1, FALSE); offset += 1; + proto_tree_add_item(tree, hf.ack_id, tvb, offset, 1, FALSE); offset += 1; + return offset; +} + +/* code to dissect NORM cmd packets */ +static void dissect_norm_cmd(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + guint8 flavor; + + offset = dissect_grrtetc(tree, tvb, offset); + flavor = tvb_get_guint8(tvb, offset); + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", + val_to_str(flavor, string_norm_cmd_type, "Unknown Cmd Type (0x%04x)")); + proto_tree_add_item(tree, hf.cmd_flavor, tvb, offset, 1, FALSE); offset ++; + switch(flavor) { + case NORM_CMD_CC: + offset = dissect_norm_cmd_cc(norm, tree, tvb, offset, pinfo); + break; + case NORM_CMD_FLUSH: + offset = dissect_norm_cmd_flush(norm, tree, tvb, offset, pinfo); + break; + case NORM_CMD_SQUELCH: + offset = dissect_norm_cmd_squelch(norm, tree, tvb, offset, pinfo); + break; + case NORM_CMD_REPAIR_ADV: + offset = dissect_norm_cmd_repairadv(norm, tree, tvb, offset, pinfo); + break; + case NORM_CMD_ACK_REQ: + offset = dissect_norm_cmd_ackreq(norm, tree, tvb, offset, pinfo); + break; + } + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); +} + +/* code to dissect NORM ack packets */ +static void dissect_norm_ack(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + guint8 acktype; + + proto_tree_add_item(tree, hf.ack_source, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(tree, hf.instance_id, tvb, offset, 2, FALSE); offset += 2; + acktype = tvb_get_guint8(tvb, offset); + if (check_col(pinfo->cinfo, COL_INFO)) + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", + val_to_str(acktype, string_norm_ack_type, "Unknown Ack Type (0x%04x)")); + proto_tree_add_item(tree, hf.ack_type, tvb, offset, 1, FALSE); offset += 1; + proto_tree_add_item(tree, hf.ack_id, tvb, offset, 1, FALSE); offset += 1; + proto_tree_add_item(tree, hf.ack_grtt_sec, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(tree, hf.ack_grtt_usec, tvb, offset, 4, FALSE); offset += 4; + if (offset < hdrlen2bytes(norm->hlen)) { + struct _fec_ptr f; + memset(&f, 0, sizeof f); + f.fec = &norm->fec; + f.hf = &hf.fec; + f.ett = &ett.fec; + f.prefs = &preferences.fec; + offset = dissect_norm_hdrext(norm, &f, tree, tvb, offset, pinfo); + } + + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); + +} + +/* code to dissect NORM nack packets */ +static void dissect_norm_nack(struct _norm *norm, proto_tree *tree, + tvbuff_t *tvb, guint offset, packet_info *pinfo) +{ + proto_tree_add_item(tree, hf.nack_server, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(tree, hf.instance_id, tvb, offset, 2, FALSE); offset += 2; + proto_tree_add_item(tree, hf.reserved, tvb, offset, 2, FALSE); offset += 2; + proto_tree_add_item(tree, hf.nack_grtt_sec, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(tree, hf.nack_grtt_usec, tvb, offset, 4, FALSE); offset += 4; + if (offset < hdrlen2bytes(norm->hlen)) { + struct _fec_ptr f; + memset(&f, 0, sizeof f); + f.fec = &norm->fec; + f.hf = &hf.fec; + f.ett = &ett.fec; + f.prefs = &preferences.fec; + offset = dissect_norm_hdrext(norm, &f, tree, tvb, offset, pinfo); + } + + while (offset < tvb_length(tvb)) { + proto_item *ti, *tif; + proto_tree *nack_tree, *flag_tree; + guint orig_offset = offset; + guint16 len; + ti = proto_tree_add_text(tree, tvb, offset, 8, "NACK Data"); + nack_tree = proto_item_add_subtree(ti, ett.nackdata); + proto_tree_add_item(nack_tree, hf.nack_form, tvb, offset, 1, FALSE); offset += 1; + + tif = proto_tree_add_item(nack_tree, hf.nack_flags, tvb, offset, 1, FALSE); + flag_tree = proto_item_add_subtree(tif, ett.flags); + proto_tree_add_item(flag_tree, hf.nack_flags_segment, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.nack_flags_block, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.nack_flags_info, tvb, offset, 1, FALSE); + proto_tree_add_item(flag_tree, hf.nack_flags_object, tvb, offset, 1, FALSE); + offset += 1; + len = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(nack_tree, hf.nack_length, tvb, offset, 2, FALSE); offset += 2; + proto_item_set_len(ti, 4+len); + if (len > 4) { + struct _fec_ptr f; + dissect_feccode(norm, &f, nack_tree, tvb, offset, pinfo, 1); + } + offset += len; + } + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); + +} /* Code to actually dissect the packets */ /* ==================================== */ @@ -104,111 +524,103 @@ static void dissect_norm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Logical packet representation */ struct _norm norm; - + /* Offset for subpacket dissection */ guint offset; - + /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *norm_tree; - + /* Structures and variables initialization */ offset = 0; memset(&norm, 0, sizeof(struct _norm)); - + /* Update packet info */ pinfo->current_proto = "NORM"; - + /* Make entries in Protocol column and Info column on summary display */ if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "NORM"); - if (check_col(pinfo->cinfo, COL_INFO)) + if (check_col(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO); - + /* NORM header dissection, part 1 */ /* ------------------------------ */ - + norm.version = hi_nibble(tvb_get_guint8(tvb, offset)); - + if (tree) { /* Create subtree for the NORM protocol */ ti = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE); norm_tree = proto_item_add_subtree(ti, ett.main); - + /* Fill the NORM subtree */ proto_tree_add_uint(norm_tree, hf.version, tvb, offset, 1, norm.version); - + } else norm_tree = NULL; - + /* This dissector supports only NORMv1 packets. * If norm.version > 1 print only version field and quit. */ if (norm.version == 1) { - + /* NORM header dissection, part 2 */ /* ------------------------------ */ - + norm.type = lo_nibble(tvb_get_guint8(tvb, offset)); norm.hlen = tvb_get_guint8(tvb, offset+1); norm.sequence = tvb_get_ntohs(tvb, offset+2); norm.source_id = tvb_get_ntohl(tvb, offset+4); - + if (tree) { proto_tree_add_uint(norm_tree, hf.type, tvb, offset, 1, norm.type); proto_tree_add_uint(norm_tree, hf.hlen, tvb, offset+1, 1, norm.hlen); proto_tree_add_uint(norm_tree, hf.sequence, tvb, offset+2, 2, norm.sequence); - proto_tree_add_uint(norm_tree, hf.source_id, tvb, offset+4, 4, norm.source_id); + proto_tree_add_item(norm_tree, hf.source_id, tvb, offset+4, 4, FALSE); } - + offset += 8; - - /* Add the Payload item */ - if (tvb_length(tvb) > offset) - proto_tree_add_none_format(norm_tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); - + + /* Complete entry in Info column on summary display */ /* ------------------------------------------------ */ - if (check_col(pinfo->cinfo, COL_INFO)) - switch (norm.type) - { - case 1: - col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "INFO"); - break; - - case 2: - col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "DATA"); - break; - - case 3: - col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "CMD"); - break; - - case 4: - col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "NACK"); - break; - - case 5: - col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "ACK"); - break; - - case 6: - col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "REPORT"); - break; - - default: - col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "Unknown type"); - break; - } + col_append_sep_str(pinfo->cinfo, COL_INFO, " ", + val_to_str(norm.type, string_norm_type, "Unknown Type (0x%04x)")); + + + switch(norm.type) { + case NORM_INFO: + dissect_norm_info(&norm, norm_tree, tvb, offset, pinfo); + break; + case NORM_DATA: + dissect_norm_data(&norm, norm_tree, tvb, offset, pinfo); + break; + case NORM_CMD: + dissect_norm_cmd(&norm, norm_tree, tvb, offset, pinfo); + break; + case NORM_ACK: + dissect_norm_ack(&norm, norm_tree, tvb, offset, pinfo); + break; + case NORM_NACK: + dissect_norm_nack(&norm, norm_tree, tvb, offset, pinfo); + break; + default: + /* Add the Payload item */ + if (tvb_length(tvb) > offset) + proto_tree_add_none_format(norm_tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset); + break; + } } else { if (tree) proto_tree_add_text(norm_tree, tvb, 0, -1, "Sorry, this dissector supports NORM version 1 only"); - + /* Complete entry in Info column on summary display */ if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "Version: %u (not supported)", norm.version); @@ -221,19 +633,20 @@ void proto_reg_handoff_norm(void) if (!preferences_initialized) { - preferences_initialized = TRUE; + preferences_initialized = TRUE; handle = create_dissector_handle(dissect_norm, proto); dissector_add_handle("udp.port", handle); + //dissector_add("udp.port", 6003, handle); } norm_prefs_save(&preferences, &preferences_old); } void proto_register_norm(void) -{ +{ /* Setup NORM header fields */ static hf_register_info hf_ptr[] = { - + { &hf.version, { "Version", "norm.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf.type, @@ -243,9 +656,105 @@ void proto_register_norm(void) { &hf.sequence, { "Sequence", "norm.sequence", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf.source_id, - { "Source ID", "norm.source_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, - - FEC_FIELD_ARRAY(hf.fec, "alc"), + { "Source ID", "norm.source_id", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf.instance_id, + { "Instance", "norm.instance_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.grtt, + { "grtt", "norm.grtt", FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.backoff, + { "Backoff", "norm.backoff", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.gsize, + { "Group Size", "norm.gsize", FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.flags, + { "Flags", "norm.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}}, + { &hf.flag.repair, + { "Repair Flag", "norm.flag.repair", FT_BOOLEAN, 8, NULL, NORM_FLAG_REPAIR, "", HFILL }}, + { &hf.flag.explicit, + { "Explicit Flag", "norm.flag.explicit", FT_BOOLEAN, 8, NULL, NORM_FLAG_EXPLICIT, "", HFILL }}, + { &hf.flag.info, + { "Info Flag", "norm.flag.info", FT_BOOLEAN, 8, NULL, NORM_FLAG_INFO, "", HFILL }}, + { &hf.flag.unreliable, + { "Unreliable Flag", "norm.flag.unreliable", FT_BOOLEAN, 8, NULL, NORM_FLAG_UNRELIABLE, "", HFILL }}, + { &hf.flag.file, + { "File Flag", "norm.flag.file", FT_BOOLEAN, 8, NULL, NORM_FLAG_FILE, "", HFILL }}, + { &hf.flag.stream, + { "Stream Flag", "norm.flag.stream", FT_BOOLEAN, 8, NULL, NORM_FLAG_STREAM, "", HFILL }}, + { &hf.flag.msgstart, + { "Msg Start Flag", "norm.flag.msgstart", FT_BOOLEAN, 8, NULL, NORM_FLAG_MSG_START, "", HFILL }}, + { &hf.object_transport_id, + { "Object Transport ID", "norm.object_transport_id", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}}, + { &hf.extension, + { "Hdr Extension", "norm.hexext", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.reserved, + { "Reserved", "norm.reserved", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL}}, + { &hf.payload_len, + { "Payload Len", "norm.payload.len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.payload_offset, + { "Payload Offset", "norm.payload.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}}, + + { &hf.cmd_flavor, + { "Flavor", "norm.flavor", FT_UINT8, BASE_DEC, VALS(string_norm_cmd_type), 0x0, "", HFILL}}, + { &hf.cc_sequence, + { "CC Sequence", "norm.ccsequence", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.cc_sts, + { "Send Time secs", "norm.cc_sts", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.cc_stus, + { "Send Time usecs", "norm.cc_stus", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.cc_node_id, + { "CC Node ID", "norm.cc_node_id", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL}}, + { &hf.cc_flags, + { "CC Flags", "norm.cc_flags", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.cc_flags_clr, + { "CLR", "norm.cc_flags.clr", FT_BOOLEAN, 8, NULL, NORM_FLAG_CC_CLR, "", HFILL}}, + { &hf.cc_flags_plr, + { "PLR", "norm.cc_flags.plr", FT_BOOLEAN, 8, NULL, NORM_FLAG_CC_PLR, "", HFILL}}, + { &hf.cc_flags_rtt, + { "RTT", "norm.cc_flags.rtt", FT_BOOLEAN, 8, NULL, NORM_FLAG_CC_RTT, "", HFILL}}, + { &hf.cc_flags_start, + { "Start", "norm.cc_flags.start", FT_BOOLEAN, 8, NULL, NORM_FLAG_CC_START, "", HFILL}}, + { &hf.cc_flags_leave, + { "Leave", "norm.cc_flags.leave", FT_BOOLEAN, 8, NULL, NORM_FLAG_CC_LEAVE, "", HFILL}}, + { &hf.cc_rtt, + { "CC RTT", "norm.cc_rtt", FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.cc_rate, + { "CC Rate", "norm.cc_rate", FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.cc_transport_id, + { "CC Transport ID", "norm.cc_transport_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}}, + + { &hf.ack_source, + { "Ack Source", "norm.ack.source", FT_IPv4, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.ack_type, + { "Ack Type", "norm.ack.type", FT_UINT8, BASE_DEC, VALS(string_norm_ack_type), 0x0, "", HFILL}}, + { &hf.ack_id, + { "Ack ID", "norm.ack.id", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.ack_grtt_sec, + { "Ack GRTT Sec", "norm.ack.grtt_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.ack_grtt_usec, + { "Ack GRTT usec", "norm.ack.grtt_usec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}}, + + { &hf.nack_server, + { "NAck Server", "norm.nack.server", FT_IPv4, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.nack_grtt_sec, + { "NAck GRTT Sec", "norm.nack.grtt_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.nack_grtt_usec, + { "NAck GRTT usec", "norm.nack.grtt_usec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.nack_form, + { "NAck FORM", "norm.nack.form", FT_UINT8, BASE_DEC, VALS(string_norm_nack_form), 0x0, "", HFILL}}, + { &hf.nack_flags, + { "NAck Flags", "norm.nack.flags", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}}, + { &hf.nack_flags_segment, + { "Segment", "norm.nack.flags.segment", FT_BOOLEAN, 8, NULL, NORM_NACK_SEGMENT, "", HFILL}}, + { &hf.nack_flags_block, + { "Block", "norm.nack.flags.block", FT_BOOLEAN, 8, NULL, NORM_NACK_BLOCK, "", HFILL}}, + { &hf.nack_flags_info, + { "Info", "norm.nack.flags.info", FT_BOOLEAN, 8, NULL, NORM_NACK_INFO, "", HFILL}}, + { &hf.nack_flags_object, + { "Object", "norm.nack.flags.object", FT_BOOLEAN, 8, NULL, NORM_NACK_OBJECT, "", HFILL}}, + { &hf.nack_length, + { "NAck Length", "norm.nack.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}}, + + + FEC_FIELD_ARRAY(hf.fec, "NORM"), { &hf.payload, { "Payload", "norm.payload", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }} @@ -254,28 +763,32 @@ void proto_register_norm(void) /* Setup protocol subtree array */ static gint *ett_ptr[] = { &ett.main, - + &ett.hdrext, + &ett.flags, + &ett.streampayload, + &ett.congestioncontrol, + &ett.nackdata, FEC_SUBTREE_ARRAY(ett.fec) }; module_t *module; - + /* Clear hf and ett fields */ memset(&hf, 0xff, sizeof(struct _norm_hf)); memset(&ett, 0xff, sizeof(struct _norm_ett)); - + /* Register the protocol name and description */ proto = proto_register_protocol("Negative-acknowledgment Oriented Reliable Multicast", "NORM", "norm"); /* Register the header fields and subtrees used */ proto_register_field_array(proto, hf_ptr, array_length(hf_ptr)); proto_register_subtree_array(ett_ptr, array_length(ett_ptr)); - + /* Reset preferences */ norm_prefs_set_default(&preferences); norm_prefs_save(&preferences, &preferences_old); - + /* Register preferences */ module = prefs_register_protocol(proto, proto_reg_handoff_norm); - norm_prefs_register(&preferences, module); + norm_prefs_register(&preferences, module); } diff --git a/epan/dissectors/packet-rmt-norm.h b/epan/dissectors/packet-rmt-norm.h index c353bd9a7a..7144cafd4f 100644 --- a/epan/dissectors/packet-rmt-norm.h +++ b/epan/dissectors/packet-rmt-norm.h @@ -9,21 +9,23 @@ * By Gerald Combs <gerald@ethereal.com> * Copyright 1998 Gerald Combs * + * Extensive changes to decode more information Julian Onions + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + #ifndef __PACKET_RMT_NORM__ #define __PACKET_RMT_NORM__ @@ -41,10 +43,57 @@ struct _norm guint8 hlen; guint16 sequence; guint32 source_id; - + struct _fec fec; }; +enum { + NORM_INFO = 1, + NORM_DATA = 2, + NORM_CMD = 3, + NORM_NACK = 4, + NORM_ACK = 5, + NORM_REPORT = 6, + + NORM_CMD_FLUSH = 1, + NORM_CMD_EOT = 2, + NORM_CMD_SQUELCH = 3, + NORM_CMD_CC = 4, + NORM_CMD_REPAIR_ADV = 5, + NORM_CMD_ACK_REQ = 6, + NORM_CMD_APPLICATION = 7, + + + NORM_FLAG_REPAIR = 0x01, + NORM_FLAG_EXPLICIT = 0x02, + NORM_FLAG_INFO = 0x04, + NORM_FLAG_UNRELIABLE = 0x08, + NORM_FLAG_FILE = 0x10, + NORM_FLAG_STREAM = 0x20, + NORM_FLAG_MSG_START = 0x40, + + NORM_ACK_CC = 1, + NORM_ACK_FLUSH = 2, + + NORM_NACK_ITEMS = 1, + NORM_NACK_RANGES = 2, + NORM_NACK_ERASURES = 3, + + NORM_NACK_SEGMENT = 0x01, + NORM_NACK_BLOCK = 0x02, + NORM_NACK_INFO = 0x04, + NORM_NACK_OBJECT = 0x08, + + + NORM_FLAG_CC_CLR = 0x01, + NORM_FLAG_CC_PLR = 0x02, + NORM_FLAG_CC_RTT = 0x04, + NORM_FLAG_CC_START = 0x08, + NORM_FLAG_CC_LEAVE = 0x10, + +}; + + /* Ethereal stuff */ /* ============== */ @@ -56,9 +105,56 @@ struct _norm_hf int hlen; int sequence; int source_id; - + int instance_id; + int grtt; + int backoff; + int gsize; + int flags; + int cmd_flavor; + int reserved; + int cc_sequence; + int cc_sts; + int cc_stus; + int cc_node_id; + int cc_flags; + int cc_flags_clr; + int cc_flags_plr; + int cc_flags_rtt; + int cc_flags_start; + int cc_flags_leave; + int cc_rtt; + int cc_rate; + int cc_transport_id; + int ack_source; + int ack_type; + int ack_id; + int ack_grtt_sec; + int ack_grtt_usec; + int nack_server; + int nack_grtt_sec; + int nack_grtt_usec; + int nack_form; + int nack_length; + int nack_flags; + int nack_flags_segment; + int nack_flags_block; + int nack_flags_info; + int nack_flags_object; + struct flaglist { + int repair; + int explicit; + int info; + int unreliable; + int file; + int stream; + int msgstart; + } flag; + int object_transport_id; + int extension; + int payload_len; + int payload_offset; struct _fec_hf fec; - + int payload; }; @@ -66,7 +162,11 @@ struct _norm_hf struct _norm_ett { gint main; - + gint hdrext; + gint flags; + gint streampayload; + gint congestioncontrol; + gint nackdata; struct _fec_ett fec; }; |