From Didier Gautheron:
[obnox/wireshark/wip.git] / epan / dissectors / packet-pim.c
index e9f8c2c4a64a266690c22cbc68d7b0ca0265cd38..89346d97bdfb18e97de3fb8d412d591fc6fea639 100644 (file)
@@ -4,8 +4,8 @@
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * This program is free software; you can redistribute it and/or
 #include <string.h>
 #include <glib.h>
 
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
 #include <epan/packet.h>
 #include <epan/ipproto.h>
 #include <epan/afn.h>
 #include "packet-ipv6.h"
 #include <epan/in_cksum.h>
+#include "packet-pim.h"
 
 #define PIM_TYPE(x)    ((x) & 0x0f)
 #define PIM_VER(x)     (((x) & 0xf0) >> 4)
@@ -68,22 +65,18 @@ static dissector_handle_t ipv6_handle;
  */
 static const char *
 dissect_pimv1_addr(tvbuff_t *tvb, int offset) {
-    static char buf[512];
     guint16 flags_masklen;
 
     flags_masklen = tvb_get_ntohs(tvb, offset);
     if (flags_masklen & 0x0180) {
-       (void)snprintf(buf, sizeof(buf),
-           "(%s%s%s) ",
+       return ep_strdup_printf("(%s%s%s) ",
            flags_masklen & 0x0100 ? "S" : "",
            flags_masklen & 0x0080 ? "W" : "",
            flags_masklen & 0x0040 ? "R" : "");
-    } else
-       buf[0] = '\0';
-    (void)snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s/%u",
-       ip_to_str(tvb_get_ptr(tvb, offset + 2, 4)), flags_masklen & 0x3f);
-
-    return buf;
+    } else {
+       return ep_strdup_printf("%s/%u",
+           ip_to_str(tvb_get_ptr(tvb, offset + 2, 4)), flags_masklen & 0x3f);
+    }
 }
 
 static const value_string type1vals[] = {
@@ -121,10 +114,8 @@ dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        return offset+tvb_length_remaining(tvb, offset);
     }
 
-    if (check_col(pinfo->cinfo, COL_PROTOCOL))
-        col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIMv1");
-    if (check_col(pinfo->cinfo, COL_INFO))
-       col_clear(pinfo->cinfo, COL_INFO);
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIMv1");
+    col_clear(pinfo->cinfo, COL_INFO);
 
     if (tree) {
        ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, FALSE);
@@ -217,7 +208,6 @@ dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 
     offset += 3;       /* skip reserved stuff */
 
-    if (tree) {
        if (tvb_reported_length_remaining(tvb, offset) > 0) {
            tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1,
                    "PIM parameters");
@@ -259,7 +249,7 @@ dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
            /*
             * The rest of the packet is a multicast data packet.
             */
-           next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+           next_tvb = tvb_new_subset_remaining(tvb, offset);
 
            /*
             * It's an IP packet - determine whether it's IPv4 or IPv6.
@@ -478,7 +468,6 @@ dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        default:
            break;
        }
-    }
 done:;
 
     return offset+tvb_length_remaining(tvb, offset);
@@ -487,7 +476,7 @@ done:;
 static const char *
 dissect_pim_addr(tvbuff_t *tvb, int offset, enum pimv2_addrtype at,
        int *advance) {
-    static char buf[512];
+    emem_strbuf_t *strbuf;
     guint8 af;
     guint8 et;
     guint8 flags;
@@ -514,19 +503,18 @@ dissect_pim_addr(tvbuff_t *tvb, int offset, enum pimv2_addrtype at,
        return NULL;
     }
 
+    strbuf = ep_strbuf_new_label(NULL);
     switch (at) {
     case pimv2_unicast:
        switch (af) {
        case AFNUM_INET:
            len = 4;
-           (void)snprintf(buf, sizeof(buf), "%s",
-               ip_to_str(tvb_get_ptr(tvb, offset + 2, len)));
+           ep_strbuf_printf(strbuf, "%s", ip_to_str(tvb_get_ptr(tvb, offset + 2, len)));
            break;
 
        case AFNUM_INET6:
            len = 16;
-           (void)snprintf(buf, sizeof(buf), "%s",
-               ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 2, len)));
+           ep_strbuf_printf(strbuf, "%s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 2, len)));
            break;
        }
        if (advance)
@@ -538,13 +526,13 @@ dissect_pim_addr(tvbuff_t *tvb, int offset, enum pimv2_addrtype at,
        switch (af) {
        case AFNUM_INET:
            len = 4;
-           (void)snprintf(buf, sizeof(buf), "%s/%u",
+           ep_strbuf_printf(strbuf, "%s/%u",
                ip_to_str(tvb_get_ptr(tvb, offset + 4, len)), mask_len);
            break;
 
        case AFNUM_INET6:
            len = 16;
-           (void)snprintf(buf, sizeof(buf), "%s/%u",
+           ep_strbuf_printf(strbuf, "%s/%u",
                ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, len)), mask_len);
            break;
        }
@@ -558,18 +546,18 @@ dissect_pim_addr(tvbuff_t *tvb, int offset, enum pimv2_addrtype at,
        switch (af) {
        case AFNUM_INET:
            len = 4;
-           (void)snprintf(buf, sizeof(buf), "%s/%u",
+           ep_strbuf_printf(strbuf, "%s/%u",
                ip_to_str(tvb_get_ptr(tvb, offset + 4, len)), mask_len);
            break;
 
        case AFNUM_INET6:
            len = 16;
-           (void)snprintf(buf, sizeof(buf), "%s/%u",
+           ep_strbuf_printf(strbuf, "%s/%u",
                ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, len)), mask_len);
            break;
        }
        if (flags) {
-           (void)snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+           ep_strbuf_append_printf(strbuf,
                " (%s%s%s)",
                flags & 0x04 ? "S" : "",
                flags & 0x02 ? "W" : "",
@@ -582,7 +570,7 @@ dissect_pim_addr(tvbuff_t *tvb, int offset, enum pimv2_addrtype at,
        return NULL;
     }
 
-    return buf;
+    return strbuf->str;
 }
 
 static const value_string type2vals[] = {
@@ -595,13 +583,14 @@ static const value_string type2vals[] = {
     { 6, "Graft" },
     { 7, "Graft-Ack" },
     { 8, "Candidate-RP-Advertisement" },
-    { 0, NULL },
+    { 9, "State-Refresh" },
+    { 0, NULL }
 };
 
 /*
- * For PIM v2, see RFC 2362, and draft-ietf-pim-sm-v2-new-03 (when PIM
- * is run over IPv6, the rules for computing the PIM checksum from the
- * draft in question, not from RFC 2362, should be used).
+ * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03
+ * (when PIM is run over IPv6, the rules for computing the PIM checksum
+ * from the draft in question, not from RFC 2362, should be used).
  */
 static void
 dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
@@ -617,10 +606,8 @@ dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
     proto_tree *pimopt_tree = NULL;
     proto_item *tiopt;
 
-    if (check_col(pinfo->cinfo, COL_PROTOCOL))
-        col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM");
-    if (check_col(pinfo->cinfo, COL_INFO))
-       col_clear(pinfo->cinfo, COL_INFO);
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM");
+    col_clear(pinfo->cinfo, COL_INFO);
 
     pim_typever = tvb_get_guint8(tvb, 0);
 
@@ -790,7 +777,7 @@ dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
                        override_interval = opt_value & 0x0000ffff;
                        proto_tree_add_text(sub_tree, tvb, offset + 4, 1,
                                            "T bit is %s",
-                                           opt_value & 0x8000 ? "set" : "not set");
+                                           (opt_value & 0x80000000) ? "set" : "not set");
                        proto_tree_add_text(sub_tree, tvb, offset + 4, 2,
                                            "LAN Delay: %ums", lan_delay);
                        proto_tree_add_text(sub_tree, tvb, offset + 6, 2,
@@ -867,7 +854,7 @@ dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
            /*
             * The rest of the packet is a multicast data packet.
             */
-           next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+           next_tvb = tvb_new_subset_remaining(tvb, offset);
 
            /*
             * It's an IP packet - determine whether it's IPv4 or IPv6.
@@ -1164,6 +1151,69 @@ dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
            break;
          }
 
+       case 9: /* State-Refresh */
+         {
+           const char *s;
+           int advance;
+
+           s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
+           if (s == NULL)
+               break;
+           proto_tree_add_text(pimopt_tree, tvb, offset, advance,
+               "Group: %s", s);
+           offset += advance;
+
+           s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+           if (s == NULL)
+               break;
+           proto_tree_add_text(pimopt_tree, tvb, offset, advance,
+               "Source: %s", s);
+           offset += advance;
+
+           s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+           if (s == NULL)
+               break;
+           proto_tree_add_text(pimopt_tree, tvb, offset, advance,
+               "Originator: %s", s);
+           offset += advance;
+
+           proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Rendezvous Point Tree %s",
+               decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 1, 1,
+                   "set", "clear"));
+           proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+               "Metric Preference: %u", tvb_get_ntohl(tvb, offset) & 0x7FFFFFFF);
+           offset += 4;
+
+           proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+               "Metric: %u", tvb_get_ntohl(tvb, offset));
+           offset += 4;
+
+           proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+               "Masklen: %u", tvb_get_guint8(tvb, offset));
+           offset += 1;
+
+           proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+               "TTL: %u", tvb_get_guint8(tvb, offset));
+           offset += 1;
+
+           proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune indicator %s",
+               decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8,
+                   "set", "clear"));
+           proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune now %s",
+               decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x40, 8,
+                   "set", "clear"));
+           proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Assert override %s",
+               decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x20, 8,
+                   "set", "clear"));
+           offset += 1;
+
+           proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+               "Interval: %u", tvb_get_guint8(tvb, offset));
+           offset += 1;
+
+           break;
+         }
+
        default:
            break;
        }
@@ -1177,16 +1227,16 @@ proto_register_pim(void)
     static hf_register_info hf[] = {
       { &hf_pim_version,
        { "Version",            "pim.version",
-                               FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+                               FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
       { &hf_pim_type,
        { "Type",               "pim.type",
-                               FT_UINT8, BASE_DEC, VALS(type2vals), 0x0, "", HFILL }},
+                               FT_UINT8, BASE_DEC, VALS(type2vals), 0x0, NULL, HFILL }},
       { &hf_pim_code,
        { "Code",               "pim.code",
-                               FT_UINT8, BASE_DEC, VALS(type1vals), 0x0, "", HFILL }},
+                               FT_UINT8, BASE_DEC, VALS(type1vals), 0x0, NULL, HFILL }},
       { &hf_pim_cksum,
        { "Checksum",           "pim.cksum",
-                               FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+                               FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
     };
     static gint *ett[] = {
         &ett_pim,