Ethereal-dev: [Ethereal-dev] New dissector: FMIPv6

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Martin André <andre@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 21 Oct 2005 19:27:35 +0200
Hi,

the attached patch implements a dissector for the Fast Handovers for
Mobile IPv6 protocol (RFC4068). This patch was produced against version
0.10.13 and extends the following files:
- packet-icmpv6.c
- packet-ipv6.h
- packet-mip6.c
- packet-mip6.h

I also attached a small sample trace of an FMIPv6 protocol message exchange captured on the Previous Access Router.

We've been using it for quite a while with no problems. We'd be glad if
someone could review it.

Thanks in advance,

Martin

diff -u -r -b dissectors.old/packet-icmpv6.c dissectors/packet-icmpv6.c
--- dissectors.old/packet-icmpv6.c	2005-10-10 15:23:01.000000000 +0200
+++ dissectors/packet-icmpv6.c	2005-10-21 19:24:00.186016288 +0200
@@ -11,6 +11,8 @@
  *
  * HMIPv6 support added by Martti Kuparinen <martti.kuparinen@xxxxxx>
  *
+ * FMIPv6 support added by Martin Andre <andre@xxxxxxxxxxxxxxxxxxxxx>
+ *
  * 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
@@ -65,6 +67,10 @@
  * and
  *
  *	draft-ietf-mobileip-hmipv6-05.txt
+ * 
+ * and
+ * 
+ * 	rfc4068.txt
  */
 
 static int proto_icmpv6 = -1;
@@ -113,6 +119,59 @@
 	{ 0, NULL}
 };
 
+static const value_string names_fmip6_prrtadv_code[] = {
+	{ FMIP6_PRRTADV_MNTUP,	"MN should use AP-ID, AR-info tuple" },
+	{ FMIP6_PRRTADV_NI_HOVER,	"Network Initiated Handover trigger" },
+	{ FMIP6_PRRTADV_NORTINFO,	"No new router information" },
+	{ FMIP6_PRRTADV_LIMRTINFO,	"Limited new router information" },
+	{ FMIP6_PRRTADV_UNSOL,	"Unsolicited" },
+	{ 0,			NULL }
+};
+
+static const value_string names_fmip6_hi_code[] = {
+	{ FMIP6_HI_PCOA,	"FBU sent from previous link" },
+	{ FMIP6_HI_NOTPCOA,	"FBU sent from new link" },
+	{ 0,			NULL }
+};
+
+static const value_string names_fmip6_hack_code[] = {
+	{ FMIP6_HACK_VALID,	"Handover Accepted, NCoA valid" },
+	{ FMIP6_HACK_INVALID,	"Handover Accepted, NCoA not valid" },
+	{ FMIP6_HACK_INUSE,	"Handover Accepted, NCoA in use" },
+	{ FMIP6_HACK_ASSIGNED,	"Handover Accepted, NCoA assigned" },
+	{ FMIP6_HACK_NOTASSIGNED,	"Handover Accepted, NCoA not assigned" },
+	{ FMIP6_HACK_NOTACCEPTED,	"Handover Not Accepted, reason unspecified" },
+	{ FMIP6_HACK_PROHIBITED,	"Administratively prohibited" },
+	{ FMIP6_HACK_INSUFFICIENT,	"Insufficient resources" },
+	{ 0,			NULL }
+};
+
+static const value_string names_fmip6_ip_addr_opt_code[] = {
+	{ FMIP6_OPT_IP_ADDRESS_OPTCODE_PCOA,	"Old Care-of Address" },
+	{ FMIP6_OPT_IP_ADDRESS_OPTCODE_NCOA,	"New Care-of Address" },
+	{ FMIP6_OPT_IP_ADDRESS_OPTCODE_NAR,	"NAR's IP address" },
+	{ 0,			NULL }
+};
+
+static const value_string names_fmip6_lla_opt_code[] = {
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_WILDCARD,	"Wildcard" },
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAP,	"Link-layer Address of the New Access Point" },
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_MN,	"Link-layer Address of the MN" },
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAR,	"Link-layer Address of the NAR" },
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_SRC,	"Link-layer Address of the source" },
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_CURROUTER,	"The AP belongs to the current interface of the router" },
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOPREFIX,	"No prefix information available" },
+	{ FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOSUPPORT,	"No fast handovers support available" },
+	{ 0,			NULL }
+};
+
+static const value_string names_fmip6_naack_opt_status[] = {
+	{ FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID,	"New CoA is invalid" },
+	{ FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID_NEW,	"New CoA is invalid, use the supplied CoA" },
+	{ FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_UNRECOGNIZED,	"LLA is unrecognized" },
+	{ 0,			NULL }
+};
+
 static void
 dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
@@ -140,7 +199,7 @@
 }
 
 static void
-dissect_icmpv6opt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+dissect_icmpv6ndopt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
     proto_tree *icmp6opt_tree, *field_tree;
     proto_item *ti, *tf;
@@ -198,6 +257,9 @@
     case ND_OPT_MAP:
 	typename = "HMIPv6 MAP option";
 	break;
+    case FMIP6_OPT_NEIGHBOR_ADV_ACK:
+	typename = "Neighbor Advertisement Acknowledgment";
+	break;
     default:
 	typename = "Unknown";
 	break;
@@ -414,12 +476,161 @@
 	}
 	break;
       }
+
+    case FMIP6_OPT_NEIGHBOR_ADV_ACK:
+      {
+	struct fmip6_opt_neighbor_advertisement_ack fmip6_opt_neighbor_advertisement_ack, *opt_naack;
+	struct e_in6_addr in6;
+
+	opt_naack = &fmip6_opt_neighbor_advertisement_ack;
+	tvb_memcpy(tvb, (guint8 *)opt_naack, offset, sizeof *opt_naack);
+
+	proto_tree_add_text(icmp6opt_tree, tvb,
+			offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_optcode),
+			1, "Option-Code: %u",
+			opt_naack->fmip6_opt_optcode);
+
+	proto_tree_add_text(icmp6opt_tree, tvb,
+			offset + offsetof(struct fmip6_opt_neighbor_advertisement_ack, fmip6_opt_status),
+			1, "Status: %s",
+			val_to_str(opt_naack->fmip6_opt_status, names_fmip6_naack_opt_status, "Unknown"));
+
+	if (opt_naack->fmip6_opt_len == 3) 
+	{
+		tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*opt_naack), 16);
+		proto_tree_add_text(icmp6opt_tree, tvb,
+			offset + sizeof(*opt_naack), 
+			16, "New Care-of Address: %s",
+			ip6_to_str(&in6));
+	}
+
+	break;
+      }
     }
 
     offset += (opt->nd_opt_len << 3);
     goto again;
 }
 
+	static void
+dissect_icmpv6fmip6opt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+	proto_tree *icmp6opt_tree;
+	proto_item *ti;
+	struct fmip6_opt_hdr fmip6_opt_hdr, *opt;
+	int len;
+	char *typename;
+
+	if (!tree)
+		return;
+
+again:
+	if ((int)tvb_reported_length(tvb) <= offset)
+		return; /* No more options left */
+
+	opt = &fmip6_opt_hdr;
+	tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
+	len = opt->fmip6_opt_len << 3;
+
+	/* !!! specify length */
+	ti = proto_tree_add_text(tree, tvb, offset, len, "ICMPv6 options");
+	icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
+
+	if (len == 0) {
+		proto_tree_add_text(icmp6opt_tree, tvb,
+				offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
+				"Invalid option length: %u",
+				opt->fmip6_opt_len);
+		return; /* we must not try to decode this */
+	}
+
+	switch (opt->fmip6_opt_type) {
+		case FMIP6_OPT_IP_ADDRESS:
+			typename = "IP Address";
+			break;
+		case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
+			typename = "New Router Prefix Information";
+			break;
+		case FMIP6_OPT_LINK_LAYER_ADDRESS:
+			typename = "Link-layer Address";
+			break;
+		default:
+			typename = "Unknown";
+			break;
+	}
+
+	proto_tree_add_text(icmp6opt_tree, tvb,
+			offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_type), 1,
+			"Type: %u (%s)", opt->fmip6_opt_type, typename);
+	proto_tree_add_text(icmp6opt_tree, tvb,
+			offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_len), 1,
+			"Length: %u bytes (%u)", opt->fmip6_opt_len << 3, opt->fmip6_opt_len);
+
+	/* decode... */
+	switch (opt->fmip6_opt_type) {
+		case FMIP6_OPT_IP_ADDRESS:
+			{
+				struct fmip6_opt_ip_address fmip6_opt_ip_address, *opt_ip;
+
+				opt_ip = &fmip6_opt_ip_address;
+				tvb_memcpy(tvb, (guint8 *)opt_ip, offset, sizeof *opt_ip);
+
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
+						val_to_str(opt->fmip6_opt_optcode, names_fmip6_ip_addr_opt_code, "Unknown"));
+
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_prefix_len),
+						1, "Prefix length: %u", opt_ip->fmip6_opt_prefix_len);
+
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + offsetof(struct fmip6_opt_ip_address, fmip6_opt_ip6_address), 
+						16, "IPv6 Address: %s",
+						ip6_to_str(&opt_ip->fmip6_opt_ip6_address));
+				break;
+			}
+		case FMIP6_OPT_NEW_ROUTER_PREFIX_INFO:
+			{
+				struct fmip6_opt_new_router_prefix_info fmip6_opt_new_router_prefix_info, *opt_nr;
+
+				opt_nr = &fmip6_opt_new_router_prefix_info;
+				tvb_memcpy(tvb, (guint8 *)opt_nr, offset, sizeof *opt_nr);
+
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %u",
+						opt->fmip6_opt_optcode);
+
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix_len),
+						1, "Prefix length: %u", opt_nr->fmip6_opt_prefix_len);
+
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + offsetof(struct fmip6_opt_new_router_prefix_info, fmip6_opt_prefix), 
+						16, "Prefix: %s",
+						ip6_to_str(&opt_nr->fmip6_opt_prefix));
+				break;
+			}
+			break;
+		case FMIP6_OPT_LINK_LAYER_ADDRESS:
+			{
+				int len, p;
+
+				p = offset + sizeof(*opt);
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + offsetof(struct fmip6_opt_hdr, fmip6_opt_optcode), 1, "Option-Code: %s",
+						val_to_str(opt->fmip6_opt_optcode, names_fmip6_lla_opt_code, "Unknown"));
+				len = (opt->fmip6_opt_len << 3) - sizeof(*opt);
+				proto_tree_add_text(icmp6opt_tree, tvb,
+						offset + sizeof(*opt), len, "Link-layer address: %s",
+						bytestring_to_str(tvb_get_ptr(tvb, p, len), len, ':'));
+				break;
+			}
+	}
+
+	offset += (opt->fmip6_opt_len << 3);
+	goto again;
+}
+
 /*
  * draft-ietf-ipngwg-icmp-name-lookups-07.txt
  * Note that the packet format was changed several times in the past.
@@ -1197,6 +1408,31 @@
 	codename = "Should always be zero";
 	colcodename = NULL;
 	break;
+		case ICMP6_EXPERIMENTAL_MOBILITY:
+			typename = coltypename ="Experimental Mobility";
+			switch (dp->icmp6_data8[0]) {
+				case FMIP6_SUBTYPE_RTSOLPR:
+					typename = coltypename ="RtSolPr (ICMPv6 Experimental Mobility)";
+					codename = "Should always be zero";
+					colcodename = NULL;
+					break;
+				case FMIP6_SUBTYPE_PRRTADV:
+					typename = coltypename ="PrRtAdv (ICMPv6 Experimental Mobility)";
+					codename = val_to_str(dp->icmp6_code, names_fmip6_prrtadv_code, "Unknown");
+					colcodename = NULL;
+					break;
+				case FMIP6_SUBTYPE_HI:
+					typename = coltypename ="HI (ICMPv6 Experimental Mobility)";
+					codename = val_to_str(dp->icmp6_code, names_fmip6_hi_code, "Unknown");
+					colcodename = NULL;
+					break;
+				case FMIP6_SUBTYPE_HACK:
+					typename = coltypename ="HAck (ICMPv6 Experimental Mobility)";
+					codename = val_to_str(dp->icmp6_code, names_fmip6_hack_code, "Unknown");
+					colcodename = NULL;
+					break;
+			}
+			break;
     }
 
     if (check_col(pinfo->cinfo, COL_INFO)) {
@@ -1375,7 +1611,7 @@
 		ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb, offset + sizeof *dp, sizeof (struct e_in6_addr)))));
 	    break;
 	case ND_ROUTER_SOLICIT:
-	    dissect_icmpv6opt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
+	    dissect_icmpv6ndopt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
 	    break;
 	case ICMP6_MLDV2_REPORT: {
 	  guint16 nbRecords;
@@ -1423,7 +1659,7 @@
 	    proto_tree_add_text(icmp6_tree, tvb,
 		offset + offsetof(struct nd_router_advert, nd_ra_retransmit), 4,
 		"Retrans time: %u", pntohl(&ra->nd_ra_retransmit));
-	    dissect_icmpv6opt(tvb, offset + sizeof(struct nd_router_advert), pinfo, icmp6_tree);
+	    dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_router_advert), pinfo, icmp6_tree);
 	    break;
 	  }
 	case ND_NEIGHBOR_SOLICIT:
@@ -1442,7 +1678,7 @@
 #endif
 			ip6_to_str(&ns->nd_ns_target));
 
-	    dissect_icmpv6opt(tvb, offset + sizeof(*ns), pinfo, icmp6_tree);
+	    dissect_icmpv6ndopt(tvb, offset + sizeof(*ns), pinfo, icmp6_tree);
 	    break;
 	  }
 	case ND_NEIGHBOR_ADVERT:
@@ -1477,7 +1713,7 @@
 #endif
 			ip6_to_str(&na_target));
 
-	    dissect_icmpv6opt(tvb, offset + sizeof(struct nd_neighbor_advert), pinfo, icmp6_tree);
+	    dissect_icmpv6ndopt(tvb, offset + sizeof(struct nd_neighbor_advert), pinfo, icmp6_tree);
 	    break;
 	  }
 	case ND_REDIRECT:
@@ -1506,7 +1742,7 @@
 #endif
 			ip6_to_str(&rd->nd_rd_dst));
 
-	    dissect_icmpv6opt(tvb, offset + sizeof(*rd), pinfo, icmp6_tree);
+	    dissect_icmpv6ndopt(tvb, offset + sizeof(*rd), pinfo, icmp6_tree);
 	    break;
 	  }
 	case ICMP6_ROUTER_RENUMBERING:
@@ -1583,7 +1819,76 @@
 		offset + 7, 1, "Reserved: %d",
 		tvb_get_guint8(tvb, offset + 7));
 	    /* Show all options */
-	    dissect_icmpv6opt(tvb, offset + 8, pinfo, icmp6_tree);
+	    dissect_icmpv6ndopt(tvb, offset + 8, pinfo, icmp6_tree);
+	    break;
+			case ICMP6_EXPERIMENTAL_MOBILITY:
+		switch (dp->icmp6_data8[0]) {
+			case FMIP6_SUBTYPE_RTSOLPR:
+				{
+					struct fmip6_rtsolpr *rtsolpr;
+					rtsolpr = (struct fmip6_rtsolpr*) dp;
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 4, 1,
+							"Subtype: Router Solicitation for Proxy Advertisement");
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 6, 2,
+							"Identifier: %d", pntohs(&rtsolpr->fmip6_rtsolpr_id));
+					dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
+					break;
+				}
+			case FMIP6_SUBTYPE_PRRTADV:
+				{
+					struct fmip6_prrtadv *prrtadv;
+					prrtadv = (struct fmip6_prrtadv*) dp;
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 4, 1,
+							"Subtype: Proxy Router Advertisement");
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 6, 2,
+							"Identifier: %d", pntohs(&prrtadv->fmip6_prrtadv_id));
+					dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
+					break;
+				}
+			case FMIP6_SUBTYPE_HI:
+				{
+					struct fmip6_hi *hi;
+					int flagoff;
+					guint8 hi_flags;
+					hi = (struct fmip6_hi*) dp;
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 4, 1,
+							"Subtype: Handover Initiate");
+
+					flagoff = offset + offsetof(struct fmip6_hi, fmip6_hi_flags_reserved);
+					hi_flags = tvb_get_guint8(tvb, flagoff);
+					tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", hi_flags);
+					field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+					proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+							decode_boolean_bitfield(hi_flags,
+								FMIP_HI_FLAG_ASSIGNED, 8, "Assigned", "Not assigned"));
+					proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+							decode_boolean_bitfield(hi_flags,
+								FMIP_HI_FLAG_BUFFER, 8, "Buffered", "Not buffered"));
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 6, 2,
+							"Identifier: %d", pntohs(&hi->fmip6_hi_id));
+					dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
+					break;
+				}
+			case FMIP6_SUBTYPE_HACK:
+				{
+					struct fmip6_hack *hack;
+					hack = (struct fmip6_hack*) dp;
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 4, 1,
+							"Subtype: Handover Acknowledge");
+					proto_tree_add_text(icmp6_tree, tvb,
+							offset + 6, 2,
+							"Identifier: %d", pntohs(&hack->fmip6_hack_id));
+					dissect_icmpv6fmip6opt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
+					break;
+				}
+		}
 	    break;
 	default:
 	    next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
Seulement dans dissectors: .packet-icmpv6.c.swp
diff -u -r -b dissectors.old/packet-ipv6.h dissectors/packet-ipv6.h
--- dissectors.old/packet-ipv6.h	2005-10-10 15:23:06.000000000 +0200
+++ dissectors/packet-ipv6.h	2005-10-21 16:58:50.402104704 +0200
@@ -12,6 +12,8 @@
  *
  * HMIPv6 support added by Martti Kuparinen <martti.kuparinen@xxxxxx>
  *
+ * FMIPv6 support added by Martin Andre <andre@xxxxxxxxxxxxxxxxxxxxx>
+ *
  * 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
@@ -534,6 +536,168 @@
 #define ICMP6_RR_RESULT_FLAGS_OOB		0x0002
 #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN		0x0001
 
+
+/*
+ * FMIPv6
+ */
+
+#define ICMP6_EXPERIMENTAL_MOBILITY	150	/* ICMP Experimental Mobility Protocol Type */
+
+#define FMIP6_SUBTYPE_RTSOLPR   2   /* Router Solicitation for Proxy Advertisement                  */
+#define FMIP6_RTSOLPR_CODE      0   /* Currently the only code for RTSOLPR                          */
+
+#define FMIP6_SUBTYPE_PRRTADV   3   /* Proxy Router Advertisement                                   */
+#define FMIP6_PRRTADV_MNTUP     0   /* MN should use AP-ID, AR-info tuple                           */
+#define FMIP6_PRRTADV_NI_HOVER  1   /* LLA of the AP is present, Network Initiated Handover trigger */
+#define FMIP6_PRRTADV_NORTINFO  2   /* No new router information is present                         */
+#define FMIP6_PRRTADV_LIMRTINFO 3   /* Limited new router information is present                    */
+#define FMIP6_PRRTADV_UNSOL     4   /* Subnet info for neighbor Access Points are sent unsolicited  */
+
+#define FMIP6_SUBTYPE_HI        4   /* Handover Initiate                                            */
+#define FMIP6_HI_PCOA           0   /* PAR receives FBU with PCoA as source IP address              */
+#define FMIP6_HI_NOTPCOA        1   /* PAR receives FBU whose source IP address is not PCoA         */
+
+#define FMIP6_SUBTYPE_HACK      5   /* Handover Acknowledge                                         */
+#define FMIP6_HACK_VALID        0   /* Handover Accepted, NCoA valid                                */
+#define FMIP6_HACK_INVALID      1   /* Handover Accepted, NCoA not valid                            */
+#define FMIP6_HACK_INUSE        2   /* Handover Accepted, NCoA in use                               */
+#define FMIP6_HACK_ASSIGNED     3   /* Handover Accepted, NCoA assigned                             */
+#define FMIP6_HACK_NOTASSIGNED  4   /* Handover Accepted, NCoA not assigned                         */
+#define FMIP6_HACK_NOTACCEPTED  128 /* Handover Not Accepted, reason unspecified                    */
+#define FMIP6_HACK_PROHIBITED   129 /* Administratively prohibited                                  */
+#define FMIP6_HACK_INSUFFICIENT 130 /* Insufficient resources                                       */
+
+/* Fast Handover Mobile IPv6 extension: Router Solicitation for Proxy Advertisement (RtSolPr).  */
+struct fmip6_rtsolpr {
+	struct icmp6_hdr fmip6_rtsolpr_hdr;
+};
+#define fmip6_rtsolpr_type     fmip6_rtsolpr_hdr.icmp6_type
+#define fmip6_rtsolpr_code     fmip6_rtsolpr_hdr.icmp6_code
+#define fmip6_rtsolpr_cksum    fmip6_rtsolpr_hdr.icmp6_cksum
+#define fmip6_rtsolpr_subtype  fmip6_rtsolpr_hdr.icmp6_data8[0]
+#define fmip6_rtsolpr_reserved fmip6_rtsolpr_hdr.icmp6_data8[1]
+#define fmip6_rtsolpr_id       fmip6_rtsolpr_hdr.icmp6_data16[1]
+
+/* Fast Handover Mobile IPv6 extension: Proxy Router Advertisement (PrRtAdv).  */
+struct fmip6_prrtadv {
+	struct icmp6_hdr fmip6_prrtadv_hdr;
+};
+
+#define fmip6_prrtadv_type     fmip6_prrtadv_hdr.icmp6_type
+#define fmip6_prrtadv_code     fmip6_prrtadv_hdr.icmp6_code
+#define fmip6_prrtadv_cksum    fmip6_prrtadv_hdr.icmp6_cksum
+#define fmip6_prrtadv_subtype  fmip6_prrtadv_hdr.icmp6_data8[0]
+#define fmip6_prrtadv_reserved fmip6_prrtadv_hdr.icmp6_data8[1]
+#define fmip6_prrtadv_id       fmip6_prrtadv_hdr.icmp6_data16[1]
+
+/* Fast Handover Mobile IPv6 extension: Handover Initiate (HI).  */
+struct fmip6_hi {
+	struct icmp6_hdr fmip6_hi_hdr;
+};
+
+#define fmip6_hi_type           fmip6_hi_hdr.icmp6_type
+#define fmip6_hi_code           fmip6_hi_hdr.icmp6_code
+#define fmip6_hi_cksum          fmip6_hi_hdr.icmp6_cksum
+#define fmip6_hi_subtype        fmip6_hi_hdr.icmp6_data8[0]
+#define fmip6_hi_flags_reserved fmip6_hi_hdr.icmp6_data8[1]
+#define fmip6_hi_id             fmip6_hi_hdr.icmp6_data16[1]
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define FMIP_HI_FLAG_ASSIGNED 0x8000
+#define FMIP_HI_FLAG_BUFFER   0x4000
+#endif /* BIG_ENDIAN */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define FMIP_HI_FLAG_ASSIGNED 0x0080
+#define FMIP_HI_FLAG_BUFFER   0x0040
+#endif /* LITTLE_ENDIAN */
+
+/* Fast Handover Mobile IPv6 extension: Handover Acknowledge (HAck).  */
+struct fmip6_hack {
+	struct icmp6_hdr fmip6_hack_hdr;
+};
+
+#define fmip6_hack_type		fmip6_hack_hdr.icmp6_type
+#define fmip6_hack_code		fmip6_hack_hdr.icmp6_code
+#define fmip6_hack_cksum	fmip6_hack_hdr.icmp6_cksum
+#define fmip6_hack_subtype	fmip6_hack_hdr.icmp6_data8[0]
+#define fmip6_hack_reserved	fmip6_hack_hdr.icmp6_data8[1]
+#define fmip6_hack_id		fmip6_hack_hdr.icmp6_data16[1]
+
+#define FMIP6_OPT_IP_ADDRESS             17 /* IP Address Option                            */
+#define FMIP6_OPT_NEW_ROUTER_PREFIX_INFO 18 /* New Router Prefix Information Option         */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS     19 /* Link-Layer Address Option                    */
+#define FMIP6_OPT_NEIGHBOR_ADV_ACK       20 /* Neighbor Advertisement Acknowledgment Option */
+
+struct fmip6_opt_hdr {
+    guint8 fmip6_opt_type;
+    guint8 fmip6_opt_len;     /* size of this option in 8 octets including opt_hdr */
+    guint8 fmip6_opt_optcode; /* Option-Code see the definition below              */
+};
+
+/* IP Address Option */
+struct fmip6_opt_ip_address {
+    guint8 fmip6_opt_type;                   /* Type = 17                                         */
+    guint8 fmip6_opt_len;                    /* size of this option in 8 octets including opt_hdr */
+    guint8 fmip6_opt_optcode;                /* Option-Code see the definition below              */
+    guint8 fmip6_opt_prefix_len;             /* Prefix length for the address                     */
+    guint32 fmip6_opt_reserved;              /* Reserved                                          */
+    struct e_in6_addr fmip6_opt_ip6_address; /* IP address                                        */
+};
+
+#define FMIP6_OPT_IP_ADDRESS_OPTCODE_PCOA 1 /* Old Care-of Address                                 */
+#define FMIP6_OPT_IP_ADDRESS_OPTCODE_NCOA 2 /* New Care-of Address                                 */
+#define FMIP6_OPT_IP_ADDRESS_OPTCODE_NAR  3 /* NAR's IP address                                    */
+#define FMIP6_OPT_IP_ADDRESS_LEN          3 /* Length of this option in 8 octets including opt_hdr */
+
+/* New Router Prefix Information Option */
+struct fmip6_opt_new_router_prefix_info {
+	guint8 fmip6_opt_type;              /* Type = 18 */
+	guint8 fmip6_opt_len;               /* size of this option in 8 octets including opt_hdr */
+	guint8 fmip6_opt_optcode;           /* Opt-Code see the definition below */
+	guint8 fmip6_opt_prefix_len;        /* Prefix length for the address */
+	guint32 fmip6_opt_reserved;         /* Reserved */	
+	struct e_in6_addr fmip6_opt_prefix; /* Could be either IPaddr or Prefix, if prefix left should be zero cleared */
+};
+
+#define FMIP6_OPT_NEW_ROUTER_PREFIX_INFO_OPTCODE 0 /* Currently no other sub-type                         */
+#define FMIP6_OPT_NEW_ROUTER_PREFIX_INFO_LEN     3 /* Length of this option in 8 octets including opt_hdr */
+
+/* Link-layer Address (LLA) Option */
+struct fmip6_opt_link_layer_address {
+    guint8 fmip6_opt_type;    /* Type = 19                                         */
+    guint8 fmip6_opt_len;     /* size of this option in 8 octets including opt_hdr */
+    guint8 fmip6_opt_optcode; /* Opt-Code see the definition below                 */
+    guchar fmip6_opt_lla[6];  /* The variable length link-layer address            */
+};
+
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_WILDCARD	0	/* wildcard requesting resolution for all nearby access points */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAP	1	/* Link-layer Address of the New Access Point */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_MN		2	/* Link-layer Address of the MN */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NAR	3	/* Link-layer Address of the NAR (i.e., Proxied Originator) */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_SRC	4	/* Link-layer Address of the source of RtSolPr or PrRtAdv message */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_CURROUTER	5	/* The access point identified by the LLA belongs to the current interface of the router */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOPREFIX	6	/* No prefix information available for the access point identified by the LLA */
+#define FMIP6_OPT_LINK_LAYER_ADDRESS_OPTCODE_NOSUPPORT	7	/* No fast handovers support available for the access point identified by the LLA */
+/* Length of this option in 8 octets including opt_hdr, is variable */
+
+/* Neighbor Advertisement Acknowledgment (NAACK) */
+struct fmip6_opt_neighbor_advertisement_ack {
+	guint8 fmip6_opt_type; 	/* Type = 20 */
+	guint8 fmip6_opt_len;		/* size of this option in 8 octets including opt_hdr (1 or 3), because NAACK is caried in a RA (ICMP, not MH) */
+	guint8 fmip6_opt_optcode;	/* Sub-types see the definition below */
+	guint8 fmip6_opt_status;	/* See the below definitions */
+	guint32 fmip6_opt_reserved;	/* Reserved */
+	/* could be followed by New CoA */
+};
+
+#define FMIP6_OPT_NEIGHBOR_ADV_ACK_OPTCODE		0	/* Currently no other sub-type */
+#define	FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID 	1	/* New CoA is invalid */
+#define	FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_INVALID_NEW 	2	/* New CoA is invalid, use the supplied CoA in reserved field */
+#define	FMIP6_OPT_NEIGHBOR_ADV_ACK_STATUS_UNRECOGNIZED 	128	/* LLA is unrecognized */
+#define FMIP6_OPT_NEIGHBOR_ADV_ACK_LEN_NO_COA		1	/* No CoA included */
+#define FMIP6_OPT_NEIGHBOR_ADV_ACK_LEN_COA		3	/* CoA included */
+
+
 void capture_ipv6(const guchar *, int, int, packet_counts *);
 
 
diff -u -r -b dissectors.old/packet-mip6.c dissectors/packet-mip6.c
--- dissectors.old/packet-mip6.c	2005-10-10 15:22:57.000000000 +0200
+++ dissectors/packet-mip6.c	2005-10-21 19:14:38.285438160 +0200
@@ -5,6 +5,8 @@
  * Routines for Mobile IPv6 dissection (draft-ietf-mobileip-ipv6-20.txt)
  * Copyright 2003 Oy L M Ericsson Ab <teemu.rinta-aho@xxxxxxxxxxx>
  *
+ * FMIPv6 support added by Martin Andre <andre@xxxxxxxxxxxxxxxxxxxxx>
+ *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@xxxxxxxxxxxx>
  * Copyright 1998 Gerald Combs
@@ -69,6 +71,18 @@
 static int hf_mip6_be_status = -1;
 static int hf_mip6_be_haddr = -1;
 
+static int hf_fmip6_fbu_seqnr = -1;
+static int hf_fmip6_fbu_a_flag = -1;
+static int hf_fmip6_fbu_h_flag = -1;
+static int hf_fmip6_fbu_l_flag = -1;
+static int hf_fmip6_fbu_k_flag = -1;
+static int hf_fmip6_fbu_lifetime = -1;
+
+static int hf_fmip6_fback_status = -1;
+static int hf_fmip6_fback_k_flag = -1;
+static int hf_fmip6_fback_seqnr = -1;
+static int hf_fmip6_fback_lifetime = -1;
+
 static int hf_mip6_bra_interval = -1;
 
 static int hf_mip6_acoa_acoa = -1;
@@ -78,6 +92,8 @@
 
 static int hf_mip6_bad_auth = -1;
 
+static int hf_fmip6_lla_optcode = -1;
+
 /* Initialize the subtree pointers */
 static gint ett_mip6 = -1;
 static gint ett_mip6_opt_padn = -1;
@@ -85,6 +101,7 @@
 static gint ett_mip6_opt_acoa = -1;
 static gint ett_mip6_opt_ni = -1;
 static gint ett_mip6_opt_bad = -1;
+static gint ett_fmip6_opt_lla = -1;
 
 /* Functions to dissect the mobility headers */
 
@@ -309,6 +326,101 @@
     return MIP6_DATA_OFF+1;
 }
 
+static int
+dissect_fmip6_fbu(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+    proto_tree *data_tree = NULL;
+    proto_item *ti;
+    int lifetime;
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_set_str(pinfo->cinfo, COL_INFO, "Fast Binding Update");
+
+    if (mip6_tree) {
+        ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
+                                 MIP6_BU_LEN, "Fast Binding Update");
+        data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+        proto_tree_add_item(data_tree, hf_fmip6_fbu_seqnr, tvb,
+                            FMIP6_FBU_SEQNR_OFF, FMIP6_FBU_SEQNR_LEN, FALSE);
+
+        proto_tree_add_item(data_tree, hf_fmip6_fbu_a_flag, tvb, 
+                            FMIP6_FBU_FLAGS_OFF, FMIP6_FBU_FLAGS_LEN, FALSE);
+        proto_tree_add_item(data_tree, hf_fmip6_fbu_h_flag, tvb, 
+                            FMIP6_FBU_FLAGS_OFF, FMIP6_FBU_FLAGS_LEN, FALSE);
+        proto_tree_add_item(data_tree, hf_fmip6_fbu_l_flag, tvb, 
+                            FMIP6_FBU_FLAGS_OFF, FMIP6_FBU_FLAGS_LEN, FALSE);
+        proto_tree_add_item(data_tree, hf_fmip6_fbu_k_flag, tvb, 
+                            FMIP6_FBU_FLAGS_OFF, FMIP6_FBU_FLAGS_LEN, FALSE);
+
+        lifetime = tvb_get_ntohs(tvb, FMIP6_FBU_LIFETIME_OFF);
+        proto_tree_add_uint_format(data_tree, hf_fmip6_fbu_lifetime, tvb,
+                                   FMIP6_FBU_LIFETIME_OFF, 
+                                   FMIP6_FBU_LIFETIME_LEN, lifetime,
+                                   "Lifetime: %d (%ld seconds)",
+                                   lifetime, (long)lifetime * 4);
+    }
+
+    return MIP6_DATA_OFF+FMIP6_FBU_LEN;
+}
+
+static int
+dissect_fmip6_fback(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+    proto_tree *data_tree = NULL;
+    proto_item *ti;
+    int lifetime;
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_set_str(pinfo->cinfo, COL_INFO, "Fast Binding Acknowledgement");
+
+    if (mip6_tree) {
+        ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
+                                 FMIP6_FBACK_LEN, "Fast Binding Acknowledgement");
+        data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+        proto_tree_add_item(data_tree, hf_fmip6_fback_status, tvb,
+                            FMIP6_FBACK_STATUS_OFF, FMIP6_FBACK_STATUS_LEN, FALSE);
+        proto_tree_add_item(data_tree, hf_fmip6_fback_k_flag, tvb, 
+                            FMIP6_FBACK_FLAGS_OFF, FMIP6_FBACK_FLAGS_LEN, FALSE);
+        proto_tree_add_item(data_tree, hf_fmip6_fback_seqnr, tvb,
+                            FMIP6_FBACK_SEQNR_OFF, FMIP6_FBACK_SEQNR_LEN, FALSE);
+        lifetime = tvb_get_ntohs(tvb, FMIP6_FBACK_LIFETIME_OFF);
+        proto_tree_add_uint_format(data_tree, hf_fmip6_fback_lifetime, tvb,
+                                   FMIP6_FBACK_LIFETIME_OFF, 
+                                   FMIP6_FBACK_LIFETIME_LEN, lifetime,
+                                   "Lifetime: %d (%ld seconds)",
+                                   lifetime, (long)lifetime * 4);
+    }
+
+    return MIP6_DATA_OFF+FMIP6_FBACK_LEN;
+}
+
+static int
+dissect_fmip6_fna(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+    proto_tree *data_tree = NULL;
+    proto_item *ti;
+/*    tvbuff_t *ipv6_tvb;*/
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_set_str(pinfo->cinfo, COL_INFO, "Fast Neighbor Advertisement");
+
+    if (mip6_tree) {
+        ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
+                                 FMIP6_FNA_LEN, "Fast Neighbor Advertisement");
+        data_tree = proto_item_add_subtree(ti, ett_mip6);
+    }
+
+	/* Create the tvbuffer for the next dissector */
+/*    ipv6_tvb = tvb_new_subset(tvb, FMIP6_FNA_LEN, -1, -1);*/
+
+	/* Call the IPv6 dissector */
+/*    dissect_ipv6(ipv6_tvb, pinfo, mip6_tree);*/
+
+	return MIP6_DATA_OFF+FMIP6_FNA_LEN;
+}
+
 /* Functions to dissect the mobility options */
 
 static void
@@ -377,6 +489,29 @@
                         optlen - MIP6_BAD_AUTH_OFF, FALSE);
 }
 
+static void
+dissect_fmip6_opt_lla(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
+                     guint optlen, packet_info *pinfo _U_,
+                     proto_tree *opt_tree)
+{
+    proto_tree *field_tree = NULL;
+    proto_item *tf;
+	int len, p;
+
+	tf = proto_tree_add_text(opt_tree, tvb, offset,      optlen, "%s", optp->name);
+	field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+	proto_tree_add_item(field_tree, hf_fmip6_lla_optcode, tvb,
+						offset + FMIP6_LLA_OPTCODE_OFF, FMIP6_LLA_OPTCODE_LEN, FALSE);
+	
+	p = offset + FMIP6_LLA_LLA_OFF;
+	len = optlen - FMIP6_LLA_LLA_OFF;
+
+	proto_tree_add_text(field_tree, tvb,
+			p, len, "Link-layer address: %s",
+			bytestring_to_str(tvb_get_ptr(tvb, p, len), len, ':'));
+}
+
 static const ip_tcp_opt mip6_opts[] = {
   {
     PAD1,
@@ -426,10 +561,117 @@
     0,
     dissect_mip6_opt_bad
   },
+  {
+    LLA,
+    "Link-Layer Address",
+    &ett_fmip6_opt_lla,
+    VARIABLE_LENGTH,
+    1,
+    dissect_fmip6_opt_lla
+  },
 };
 
 #define N_MIP6_OPTS	(sizeof mip6_opts / sizeof mip6_opts[0])
 
+/* Like "dissect_ip_tcp_options()", but assumes the length of an option
+ *doesn't* include the type and length bytes. And opt-code too for LLA option */
+	void
+dissect_mipv6_options(tvbuff_t *tvb, int offset, guint length,
+		const ip_tcp_opt *opttab, int nopts, int eol,
+		packet_info *pinfo, proto_tree *opt_tree)
+{
+	guchar            opt;
+	const ip_tcp_opt *optp;
+	opt_len_type      len_type;
+	unsigned int      optlen;
+	char             *name;
+	char              name_str[7+1+1+2+2+1+1];	/* "Unknown (0x%02x)" */
+	void            (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
+			int, guint, packet_info *, proto_tree *);
+	guint             len;
+	guint             uncount = 2;
+
+	while (length > 0) {
+		opt = tvb_get_guint8(tvb, offset);
+		if (opt == LLA) ++uncount; /* let's omit opt-code */
+		for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
+			if (optp->optcode == opt)
+				break;
+		}
+		if (optp == &opttab[nopts]) {
+			/* We assume that the only NO_LENGTH options are Pad1 options,
+			   so that we can treat unknown options as VARIABLE_LENGTH with a
+			   minimum of 0, and at least be able to move on to the next option
+			   by using the length in the option. */
+			optp = NULL;	/* indicate that we don't know this option */
+			len_type = VARIABLE_LENGTH;
+			optlen = 0;
+			snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
+			name = name_str;
+			dissect = NULL;
+		} else {
+			len_type = optp->len_type;
+			optlen = optp->optlen;
+			name = optp->name;
+			dissect = optp->dissect;
+		}
+		--length;      /* account for type byte */
+		if (len_type != NO_LENGTH) {
+			/* Option has a length. Is it in the packet? */
+			if (length < uncount - 1) {
+				/* Bogus - packet must at least include omited bytes! */
+				proto_tree_add_text(opt_tree, tvb, offset,      1,
+						"%s (length byte past end of options)", name);
+				return;
+			}
+			len = tvb_get_guint8(tvb, offset + 1);  /* Size specified in option */
+			--length;    /* account for length byte */
+			if (opt == LLA) --length;    /* account for opt-code byte */
+			if (len > length) {
+				/* Bogus - option goes past the end of the header. */
+				proto_tree_add_text(opt_tree, tvb, offset,      length,
+						"%s (option length = %u byte%s says option goes past end of options)",
+						name, len, plurality(len, "", "s"));
+				return;
+			} else if (len_type == FIXED_LENGTH && len != optlen) {
+				/* Bogus - option length isn't what it's supposed to be for this
+				   option. */
+				proto_tree_add_text(opt_tree, tvb, offset,      uncount + len,
+						"%s (with option length = %u byte%s; should be %u)", name,
+						len, plurality(len, "", "s"), optlen);
+				return;
+			} else if (len_type == VARIABLE_LENGTH && len < optlen) {
+				/* Bogus - option length is less than what it's supposed to be for
+				   this option. */
+				proto_tree_add_text(opt_tree, tvb, offset,      uncount + len,
+						"%s (with option length = %u byte%s; should be >= %u)", name,
+						len, plurality(len, "", "s"), optlen);
+				return;
+			} else {
+				if (optp == NULL) {
+					proto_tree_add_text(opt_tree, tvb, offset,    uncount + len, "%s (%u byte%s)",
+							name, len, plurality(len, "", "s"));
+				} else {
+					if (dissect != NULL) {
+						/* Option has a dissector. */
+						(*dissect)(optp, tvb, offset,          uncount + len, pinfo, opt_tree);
+					} else {
+						/* Option has no data, hence no dissector. */
+						proto_tree_add_text(opt_tree, tvb, offset,  uncount + len, "%s", name);
+					}
+				}
+				offset += uncount + len;
+			}
+			length -= len;
+		} else {
+			proto_tree_add_text(opt_tree, tvb, offset,      1, "%s", name);
+			offset += 1;
+		}
+		if (opt == eol)
+			break;
+	}
+}
+
 /* Function to dissect mobility options */
 static int
 dissect_mip6_options(tvbuff_t *tvb, proto_tree *mip6_tree, int offset, int len,
@@ -445,7 +687,7 @@
                              "Mobility Options");
     opts_tree = proto_item_add_subtree(ti, ett_mip6);
 
-    dissect_ipv6_options(tvb, offset, len,
+    dissect_mipv6_options(tvb, offset, len,
        mip6_opts, N_MIP6_OPTS, -1, pinfo, opts_tree);
 
     return len;
@@ -524,6 +766,15 @@
     case BE:
         offset = dissect_mip6_be(tvb, mip6_tree, pinfo);
         break;
+    case FBU:
+        offset = dissect_fmip6_fbu(tvb, mip6_tree, pinfo);
+        break;
+    case FBACK:
+        offset = dissect_fmip6_fback(tvb, mip6_tree, pinfo);
+        break;
+    case FNA:
+        offset = dissect_fmip6_fna(tvb, mip6_tree, pinfo);
+        break;
     default:
         dissect_mip6_unknown(tvb, mip6_tree, pinfo);
         offset = len;
@@ -640,6 +891,46 @@
                                    FT_IPv6, BASE_HEX, NULL, 0,
                                    "Home Address", HFILL }},
         
+        { &hf_fmip6_fbu_seqnr,     { "Sequence number", "fmip6.fbu.seqnr",
+                                   FT_UINT16, BASE_DEC, NULL, 0,
+                                   "Sequence number", HFILL }},
+        { &hf_fmip6_fbu_a_flag,    { "Acknowledge (A) flag", "fmip6.fbu.a_flag",
+                                   FT_BOOLEAN, 8, TFS(&fmip6_fbu_a_flag_value),
+                                   0x80, "Acknowledge (A) flag", HFILL }},
+        { &hf_fmip6_fbu_h_flag,    { "Home Registration (H) flag", 
+                                   "fmip6.fbu.h_flag",
+                                   FT_BOOLEAN, 8, TFS(&fmip6_fbu_h_flag_value),
+                                   0x40, "Home Registration (H) flag", HFILL }},
+        { &hf_fmip6_fbu_l_flag,    { "Link-Local Compatibility (L) flag", 
+                                   "fmip6.fbu.l_flag",
+                                   FT_BOOLEAN, 8, TFS(&fmip6_fbu_l_flag_value),
+                                   0x20, "Home Registration (H) flag", HFILL }},
+        { &hf_fmip6_fbu_k_flag,    { "Key Management Compatibility (K) flag", 
+                                   "fmip6.fbu.k_flag",
+                                   FT_BOOLEAN, 8, TFS(&fmip6_fbu_k_flag_value),
+                                   0x10, "Key Management Compatibility (K) flag", 
+                                   HFILL }},
+        { &hf_fmip6_fbu_lifetime,  { "Lifetime", "fmip6.fbu.lifetime",
+                                   FT_UINT16, BASE_DEC, NULL, 0,
+                                   "Lifetime", HFILL }},
+        
+        { &hf_fmip6_fback_status,  { "Status", "fmip6.fback.status",
+                                   FT_UINT8, BASE_DEC,
+                                   VALS(&fmip6_fback_status_value), 0,
+                                   "Fast Binding Acknowledgement status", HFILL }},
+        { &hf_fmip6_fback_k_flag,  { "Key Management Compatibility (K) flag", 
+                                   "fmip6.fback.k_flag",
+                                   FT_BOOLEAN, 8, TFS(&fmip6_fbu_k_flag_value),
+                                   0x80, "Key Management Compatibility (K) flag", 
+                                   HFILL }},
+        { &hf_fmip6_fback_seqnr,   { "Sequence number", "fmip6.fback.seqnr",
+                                   FT_UINT16, BASE_DEC, NULL, 0,
+                                   "Sequence number", HFILL }},
+        { &hf_fmip6_fback_lifetime, { "Lifetime", "fmip6.fback.lifetime",
+                                   FT_UINT16, BASE_DEC, NULL, 0,
+                                   "Lifetime", HFILL }},
+        
+        
         { &hf_mip6_bra_interval, { "Refresh interval", "mip6.bra.interval",
                                    FT_UINT16, BASE_DEC, NULL, 0,
                                    "Refresh interval", HFILL }},
@@ -657,7 +948,11 @@
 
         { &hf_mip6_bad_auth,     { "Authenticator", "mip6.bad.auth",
                                    FT_BYTES, BASE_HEX, NULL, 0,
-                                   "Care-of nonce index", HFILL }}
+                                   "Care-of nonce index", HFILL }},
+
+        { &hf_fmip6_lla_optcode, { "Option-Code", "mip6.lla.optcode",
+                                   FT_UINT8, BASE_DEC, VALS(&fmip6_lla_optcode_value), 0,
+                                   "Option-Code", HFILL }}
     };
 
     /* Setup protocol subtree array */
@@ -668,6 +963,7 @@
         &ett_mip6_opt_acoa,
         &ett_mip6_opt_ni,
         &ett_mip6_opt_bad,
+        &ett_fmip6_opt_lla,
     };
     
     /* Register the protocol name and description */
diff -u -r -b dissectors.old/packet-mip6.h dissectors/packet-mip6.h
--- dissectors.old/packet-mip6.h	2005-10-10 15:22:57.000000000 +0200
+++ dissectors/packet-mip6.h	2005-10-21 17:05:52.574924680 +0200
@@ -3,8 +3,11 @@
  * $Id: packet-mip6.h 11410 2004-07-18 18:06:47Z gram $
  *
  * Definitions for Mobile IPv6 dissection (draft-ietf-mobileip-ipv6-20.txt)
+ * and Fast Handover for Mobile IPv6 (FMIPv6, draft-ietf-mipshop-fast-mipv6-03.txt)
  * Copyright 2003 Oy L M Ericsson Ab <teemu.rinta-aho@xxxxxxxxxxx>
  *
+ * FMIPv6 support added by Martin Andre <andre@xxxxxxxxxxxxxxxxxxxxx>
+ *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@xxxxxxxxxxxx>
  * Copyright 1998 Gerald Combs
@@ -36,7 +39,10 @@
     COT  = 4,
     BU   = 5,
     BA   = 6,
-    BE   = 7
+    BE    = 7,
+	FBU   = 8,
+	FBACK = 9,
+	FNA   = 10
 } mhTypes;
 
 static const value_string mip6_mh_types[] = {
@@ -48,6 +54,9 @@
     {BU,   "Binding Update"},
     {BA,   "Binding Acknowledgement"},
     {BE,   "Binding Error"},
+    {FBU,   "Fast Binding Update"},
+    {FBACK, "Fast Binding Acknowledgment"},
+    {FNA,   "Fast Neighbor Advertisement"},
     {0,    NULL}
 };
 
@@ -58,7 +67,8 @@
     BRA  = 2,
     ACOA = 3,
     NI   = 4,
-    BAD  = 5
+    BAD  = 5,
+	LLA  = 7
 } optTypes;
 
 /* Binding Update flag description */
@@ -108,6 +118,44 @@
     { 0, NULL }
 };
 
+/* Fast Binding Update flag description */
+static const true_false_string fmip6_fbu_a_flag_value = {
+    "Fast Binding Acknowledgement requested",
+    "Fast Binding Acknowledgement not requested"
+};
+
+static const true_false_string fmip6_fbu_h_flag_value = {
+    "Home Registration",
+    "No Home Registration"
+};
+
+static const true_false_string fmip6_fbu_l_flag_value = {
+    "Link-Local Address Compatibility",
+    "No Link-Local Address Compatibility"
+};
+
+static const true_false_string fmip6_fbu_k_flag_value = {
+    "Key Management Mobility Compatibility",
+    "No Key Management Mobility Compatibility"
+};
+
+/* Fast Binding Acknowledgement status values */
+static const value_string fmip6_fback_status_value[] = {
+    {   0, "Fast Binding Update accepted" },
+    {   1, "Accepted but use supplied NCoA" },
+    { 128, "Reason unspecified" },
+    { 129, "Administratively prohibited" },
+    { 130, "Insufficient resources" },
+    { 131, "Incorrect interface identifier length" },
+    {   0, NULL }
+};
+
+/* MH LLA Option code */
+static const value_string fmip6_lla_optcode_value[] = {
+    {   2, "Link Layer Address of the MN" },
+    {   0, NULL }
+};
+
 /* Message lengths */
 #define MIP6_BRR_LEN          2
 #define MIP6_HOTI_LEN        10
@@ -117,6 +165,9 @@
 #define MIP6_BU_LEN           6
 #define MIP6_BA_LEN           6
 #define MIP6_BE_LEN          18
+#define FMIP6_FBU_LEN         6
+#define FMIP6_FBACK_LEN       6
+#define FMIP6_FNA_LEN         2
 
 /* Field offsets & lengths for mobility headers */
 #define MIP6_PROTO_OFF        0
@@ -191,6 +242,29 @@
 #define MIP6_BE_RES_LEN       1
 #define MIP6_BE_HOA_LEN      16
 
+#define FMIP6_FBU_SEQNR_OFF     6
+#define FMIP6_FBU_FLAGS_OFF     8
+#define FMIP6_FBU_RES_OFF       9
+#define FMIP6_FBU_LIFETIME_OFF 10
+#define FMIP6_FBU_OPTS_OFF     12
+#define FMIP6_FBU_SEQNR_LEN     2
+#define FMIP6_FBU_FLAGS_LEN     1
+#define FMIP6_FBU_RES_LEN       1
+#define FMIP6_FBU_LIFETIME_LEN  2
+
+#define FMIP6_FBACK_STATUS_OFF    6
+#define FMIP6_FBACK_FLAGS_OFF     7
+#define FMIP6_FBACK_SEQNR_OFF     8
+#define FMIP6_FBACK_LIFETIME_OFF 10
+#define FMIP6_FBACK_OPTS_OFF     12
+#define FMIP6_FBACK_STATUS_LEN    1
+#define FMIP6_FBACK_FLAGS_LEN     1
+#define FMIP6_FBACK_SEQNR_LEN     2
+#define FMIP6_FBACK_LIFETIME_LEN  2
+
+#define FMIP6_FNA_RES_OFF     6
+#define FMIP6_FNA_OPTS_OFF    8
+#define FMIP6_FNA_RES_LEN     2
 /* Field offsets & field and option lengths for mobility options */
 #define MIP6_BRA_LEN          2
 #define MIP6_BRA_RI_OFF       2
@@ -208,4 +282,8 @@
 
 #define MIP6_BAD_AUTH_OFF     2
 
+#define FMIP6_LLA_OPTCODE_OFF 2
+#define FMIP6_LLA_LLA_OFF     4
+#define FMIP6_LLA_OPTCODE_LEN 1
+
 #endif /* __PACKET_MIP6_H_DEFINED__ */

Attachment: fmipv6-PAR.trace
Description: Binary data