There's no need to keep a "FILE *" for the file being printed to in a
[obnox/wireshark/wip.git] / packet-icmpv6.c
index 2fa4fd86157084b9f2dc42c892fd70f454a12569..44a34938b13b0cfc4c2fe165d59ac72f6e324961 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-icmpv6.c
  * Routines for ICMPv6 packet disassembly
  *
- * $Id: packet-icmpv6.c,v 1.69 2003/01/20 05:42:30 guy Exp $
+ * $Id: packet-icmpv6.c,v 1.75 2004/01/18 16:15:25 jmayer Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -86,6 +86,7 @@ static gint ett_nodeinfo_node4 = -1;
 static gint ett_nodeinfo_node6 = -1;
 static gint ett_nodeinfo_nodebitmap = -1;
 static gint ett_nodeinfo_nodedns = -1;
+static gint ett_multicastRR = -1;
 
 static dissector_handle_t ipv6_handle;
 static dissector_handle_t data_handle;
@@ -147,6 +148,8 @@ dissect_icmpv6opt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
     struct nd_opt_hdr nd_opt_hdr, *opt;
     int len;
     char *typename;
+    static const guint8 nd_redirect_reserved[6] = {0, 0, 0, 0, 0, 0};
+    guint8 nd_redirect_res[6];
 
     if (!tree)
        return;
@@ -216,7 +219,7 @@ again:
        char *t;
        int len, i, p;
        len = (opt->nd_opt_len << 3) - sizeof(*opt);
-       t = (char *)malloc(len * 3);
+       t = g_malloc(len * 3);
        memset(t, 0, len * 3);
        p = offset + sizeof(*opt);
        for (i = 0; i < len; i++) {
@@ -226,7 +229,7 @@ again:
        }
        proto_tree_add_text(icmp6opt_tree, tvb,
            offset + sizeof(*opt), len, "Link-layer address: %s", t);
-       free(t);
+       g_free(t);
        break;
       }
     case ND_OPT_PREFIX_INFORMATION:
@@ -272,6 +275,13 @@ again:
        break;
       }
     case ND_OPT_REDIRECTED_HEADER:
+       tvb_memcpy(tvb, (guint8 *)&nd_redirect_res, offset + 2, 6);
+       if (memcmp(nd_redirect_res, nd_redirect_reserved, 6) == 0)
+          proto_tree_add_text(icmp6opt_tree, tvb,
+           offset + 2, 6, "Reserved: 0 (correct)");
+       else
+          proto_tree_add_text(icmp6opt_tree, tvb,
+           offset +2, 6, "Reserved: MUST be 0 (incorrect!)");  
        proto_tree_add_text(icmp6opt_tree, tvb,
            offset + 8, (opt->nd_opt_len << 3) - 8, "Redirected packet");
        dissect_contained_icmpv6(tvb, offset + 8, pinfo, icmp6opt_tree);
@@ -424,11 +434,7 @@ again:
  */
 
 static const char *
-bitrange0(v, s, buf, buflen)
-       guint32 v;
-       int s;
-       char *buf;
-       int buflen;
+bitrange0(guint32 v, int s, char *buf, int buflen)
 {
        guint32 v0;
        char *p, *ep;
@@ -924,6 +930,69 @@ dissect_rrenum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
     }
 }
 
+/*
+ * See I-D draft-vida-mld-v2-03
+ */
+static const value_string mldrv2ModesNames[] = {
+  { 1, "Include" },
+  { 2, "Exclude" },
+  { 3, "Changed to include" },
+  { 4, "Changed to exclude" },
+  { 5, "Allow new sources" },
+  { 6, "Block old sources" },
+  { 0, NULL }
+};
+
+static void
+dissect_mldrv2( tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree )
+{
+  proto_tree *sub_tree;
+  proto_item *tf;
+
+  guint8 recordType, auxDataLen;
+  guint32 sourceNb, recordSize, localOffset;
+  struct e_in6_addr addr;
+
+  for( ; count; count--, offset += recordSize ) {
+    localOffset = offset;
+    recordType = tvb_get_guint8( tvb, localOffset );
+    localOffset += 1;
+    auxDataLen = tvb_get_guint8( tvb, localOffset );
+    localOffset += 1;
+    sourceNb = tvb_get_ntohs( tvb, localOffset );
+    localOffset += 2;
+    recordSize = 4 + 16 + (16 * sourceNb) + (auxDataLen * 4);
+
+    tvb_memcpy(tvb, (guint8 *)&addr, localOffset, sizeof(addr) );
+    tf = proto_tree_add_text( tree, tvb, offset, recordSize, 
+#ifdef INET6
+                             "%s: %s (%s)", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
+                             get_hostname6(&addr), ip6_to_str(&addr) 
+#else
+                             "%s: %s", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
+                             ip6_to_str(&addr) 
+#endif
+                             );
+    sub_tree = proto_item_add_subtree(tf, ett_multicastRR);
+
+    proto_tree_add_text( sub_tree, tvb, offset,   1, "Mode: %s", 
+                        val_to_str(recordType, mldrv2ModesNames,"Unknown mode") );
+    proto_tree_add_text( sub_tree, tvb, offset+1, 1, "Aux data len: %u", auxDataLen * 4);
+    proto_tree_add_text( sub_tree, tvb, localOffset, 16, "Multicast Address: %s", ip6_to_str(&addr) );
+    localOffset += 16;
+
+    for( ; sourceNb; sourceNb--, localOffset += 16 ) {
+      tvb_memcpy(tvb, (guint8 *)&addr, localOffset, sizeof(addr) );
+      proto_tree_add_text( sub_tree, tvb, localOffset, 16, 
+#ifdef INET6
+                          "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr) );
+#else
+                          "Source Address: %s", ip6_to_str(&addr) );
+#endif
+    }
+  }
+}
+
 static void
 dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
@@ -1098,6 +1167,31 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
            "Unknown");
        len = sizeof(struct icmp6_nodeinfo);
        break;
+    case ICMP6_MIP6_DHAAD_REQUEST:
+       typename = coltypename = "Dynamic Home Agent Address Discovery Request";
+       codename = "Should always be zero";
+       colcodename = NULL;
+       break;
+    case ICMP6_MIP6_DHAAD_REPLY:
+       typename = coltypename = "Dynamic Home Agent Address Discovery Reply";
+       codename = "Should always be zero";
+       colcodename = NULL;
+       break;
+    case ICMP6_MIP6_MPS:
+       typename = coltypename = "Mobile Prefix Solicitation";
+       codename = "Should always be zero";
+       colcodename = NULL;
+       break;
+    case ICMP6_MIP6_MPA:
+       typename = coltypename = "Mobile Prefix Advertisement";
+       codename = "Should always be zero";
+       colcodename = NULL;
+       break;
+    case ICMP6_MLDV2_REPORT:
+       typename = coltypename = "Multicast Listener Report Message v2";
+       codename = "Should always be zero";
+       colcodename = NULL;
+       break;
     }
 
     if (check_col(pinfo->cinfo, COL_INFO)) {
@@ -1229,6 +1323,13 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        case ND_ROUTER_SOLICIT:
            dissect_icmpv6opt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
            break;
+       case ICMP6_MLDV2_REPORT: {
+         guint16 nbRecords;
+         
+         nbRecords = tvb_get_ntohs( tvb, offset+4+2 );
+         dissect_mldrv2( tvb, offset+4+2+2, nbRecords, icmp6_tree );
+         break;
+       }
        case ND_ROUTER_ADVERT:
          {
            struct nd_router_advert nd_router_advert, *ra;
@@ -1368,6 +1469,53 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                "Unknown"));
            dissect_nodeinfo(tvb, offset, pinfo, icmp6_tree);
            break;
+       case ICMP6_MIP6_DHAAD_REQUEST:
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 4, 2, "Identifier: %d (0x%02x)",
+               tvb_get_ntohs(tvb, offset + 4),
+               tvb_get_ntohs(tvb, offset + 4));
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 6, 2, "Reserved: %d",
+               tvb_get_ntohs(tvb, offset + 6));
+           break;
+       case ICMP6_MIP6_DHAAD_REPLY:
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 4, 2, "Identifier: %d (0x%02x)",
+               tvb_get_ntohs(tvb, offset + 4),
+               tvb_get_ntohs(tvb, offset + 4));
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 6, 2, "Reserved: %d",
+               tvb_get_ntohs(tvb, offset + 6));
+           /* TODO Show all Home Agent Addresses */
+           break;
+       case ICMP6_MIP6_MPS:
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 4, 2, "Identifier: %d (0x%02x)",
+               tvb_get_ntohs(tvb, offset + 4),
+               tvb_get_ntohs(tvb, offset + 4));
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 6, 2, "Reserved: %d",
+               tvb_get_ntohs(tvb, offset + 6));
+           break;
+       case ICMP6_MIP6_MPA:
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 4, 2, "Identifier: %d (0x%02x)",
+               tvb_get_ntohs(tvb, offset + 4),
+               tvb_get_ntohs(tvb, offset + 4));
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 6, 2,
+               decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
+                   0x8000, 16,
+                   "Managed Address Configuration",
+                   "No Managed Address Configuration"));
+           proto_tree_add_text(icmp6_tree, tvb,
+               offset + 6, 2,
+               decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
+                   0x4000, 16,
+                   "Other Stateful Configuration",
+                   "No Other Stateful Configuration"));
+           /* TODO Show all options */
+           break;
        default:
            next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
            call_dissector(data_handle,next_tvb, pinfo, tree);
@@ -1404,6 +1552,7 @@ proto_register_icmpv6(void)
     &ett_nodeinfo_node6,
     &ett_nodeinfo_nodebitmap,
     &ett_nodeinfo_nodedns,
+    &ett_multicastRR,
   };
 
   proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",