Wireshark-dev: [Wireshark-dev] [PATCH] New Type : ISIS LSPID
From: Sebastien Tandel <sebastien@xxxxxxxxx>
Date: Sun, 10 Dec 2006 04:02:51 +0100
Hi all,


I am working on a stat module for ISIS and I create a new type, FT_LSPID.
Here is a patch made against the revision 20088.

Now, you can :
   - define an hf field with FT_LSPID type
   - use proto_tree_add_item or proto_tree_add_lspid with FT_LSPID
   - use lspid_to_str instead of print_system_id (which does not take an
additional length parameter)

I will send the patch with all the changes in dissectors/packet-isis-* 
tomorrow.


thanx,
Sebastien Tandel

Index: doc/README.developer
===================================================================
--- doc/README.developer	(révision 20088)
+++ doc/README.developer	(copie de travail)
@@ -956,7 +956,7 @@
 		FT_UINT32, FT_UINT64, FT_INT8, FT_INT16, FT_INT24, FT_INT32,
 		FT_INT64, FT_FLOAT, FT_DOUBLE, FT_ABSOLUTE_TIME,
 		FT_RELATIVE_TIME, FT_STRING, FT_STRINGZ, FT_UINT_STRING,
-		FT_ETHER, FT_BYTES, FT_IPv4, FT_IPv6, FT_IPXNET,
+		FT_ETHER, FT_BYTES, FT_IPv4, FT_IPv6, FT_IPXNET, FT_LSPID
 		FT_FRAMENUM, FT_PROTOCOL, FT_GUID, FT_OID
 FIELDBASE	BASE_NONE, BASE_DEC, BASE_HEX, BASE_OCT, BASE_DEC_HEX, BASE_HEX_DEC
 FIELDCONVERT	VALS(x), TFS(x), NULL
@@ -1486,6 +1486,7 @@
 				specified number of characters.
 	FT_ETHER		A six octet string displayed in
 				Ethernet-address format.
+	FT_LSPID		A eight octet string displayed in LSPID format
 	FT_BYTES		A string of bytes with arbitrary values;
 				used for raw binary data.
 	FT_IPv4			A version 4 IP address (4 bytes) displayed
Index: epan/dfilter/semcheck.c
===================================================================
--- epan/dfilter/semcheck.c	(révision 20088)
+++ epan/dfilter/semcheck.c	(copie de travail)
@@ -70,6 +70,7 @@
 		case FT_IPXNET:
 		case FT_INT64:		/* XXX - should be able to compare with INT */
 		case FT_UINT64:		/* XXX - should be able to compare with INT */
+		case FT_LSPID:
 			return a == b;
 
 		case FT_ETHER:
@@ -170,6 +171,7 @@
 		case FT_PCRE:
 		case FT_GUID:
 		case FT_OID:
+		case FT_LSPID:
 			return FALSE;
 
 		case FT_BOOLEAN:
@@ -241,6 +243,7 @@
 		case FT_IPv6:
 		case FT_GUID:
 		case FT_OID:
+		case FT_LSPID:
 			return TRUE;
 
 		case FT_NONE:
Index: epan/ftypes/ftype-bytes.c
===================================================================
--- epan/ftypes/ftype-bytes.c	(révision 20088)
+++ epan/ftypes/ftype-bytes.c	(copie de travail)
@@ -39,6 +39,7 @@
 
 #define ETHER_LEN	6
 #define IPv6_LEN	16
+#define LSPID_LEN	8
 
 static void
 bytes_fvalue_new(fvalue_t *fv)
@@ -134,6 +135,13 @@
 }
 
 static void
+lspid_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
+{
+  g_assert(!already_copied);
+  common_fvalue_set(fv, value, LSPID_LEN);
+}
+
+static void
 ipv6_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
 {
 	g_assert(!already_copied);
@@ -236,6 +244,23 @@
 }
 
 static gboolean
+lspid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
+{
+  if (bytes_from_unparsed(fv, s, TRUE, NULL)) {
+    if (fv->value.bytes->len > LSPID_LEN) {
+      logfunc("\"%s\" contains too many bytes to be a valid LSPID.", s);
+      return FALSE;
+    }
+    else if (fv->value.bytes->len < LSPID_LEN && ! allow_partial_value) {
+      logfunc("\"%s\" contains too few bytes to be a valid LSPID.", s);
+      return FALSE;
+    }
+    return TRUE;
+  }
+
+}
+
+static gboolean
 ipv6_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
 {
 	guint8	buffer[16];
@@ -264,6 +289,20 @@
 	ip6_to_str_buf((struct e_in6_addr *)fv->value.bytes->data, buf);
 }
 
+static int
+lspid_repr_len(fvalue_t *fv _U_, ftrepr_t rtype _U_)
+{
+	/*
+	 * 39 characters for "XXXX.XXXX.XXXX.XX-XX".
+	 */
+	return 20;
+}
+
+static void lspid_to_repr(fvalue_t *fv, ftrepr_t rtype _U_, char *buf)
+{
+  lspid_to_str_buf(fv->value.bytes->data, buf);
+}
+
 static gboolean
 oid_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
 {
@@ -595,6 +634,43 @@
 		slice,
 	};
 
+	static ftype_t lspid_type = {
+		FT_LSPID,			/* ftype */
+		"FT_LSPID",			/* name */
+		"ISIS LSP id",			/* pretty_name */
+		LSPID_LEN,			/* wire_size */
+		bytes_fvalue_new,		/* new_value */
+		bytes_fvalue_free,		/* free_value */
+		lspid_from_unparsed,		/* val_from_unparsed */
+		NULL,				/* val_from_string */
+		lspid_to_repr, 			/* val_to_string_repr */
+		lspid_repr_len, 		/* len_string_repr */
+
+		lspid_fvalue_set, 		/* set_value */
+		NULL,				/* set_value_integer */
+		NULL,				/* set_value_integer64 */
+		NULL,				/* set_value_floating */
+
+		value_get,			/* get_value */
+		NULL,				/* get_value_integer */
+		NULL,				/* get_value_integer64 */
+		NULL,				/* get_value_floating */
+
+		cmp_eq,
+		cmp_ne,
+		cmp_gt,
+		cmp_ge,
+		cmp_lt,
+		cmp_le,
+		cmp_bytes_bitwise_and,
+		cmp_contains,
+		NULL,				/* cmp_matches */
+
+		len,
+		slice,
+	};
+
+
 	static ftype_t ipv6_type = {
 		FT_IPv6,			/* ftype */
 		"FT_IPv6",			/* name */
@@ -672,4 +748,5 @@
 	ftype_register(FT_ETHER, &ether_type);
 	ftype_register(FT_IPv6, &ipv6_type);
 	ftype_register(FT_OID, &oid_type);
+	ftype_register(FT_LSPID, &lspid_type);
 }
Index: epan/ftypes/ftypes.h
===================================================================
--- epan/ftypes/ftypes.h	(révision 20088)
+++ epan/ftypes/ftypes.h	(copie de travail)
@@ -62,6 +62,7 @@
 	FT_PCRE,		/* a compiled Perl-Compatible Regular Expression object */
 	FT_GUID,		/* GUID, UUID */
 	FT_OID,			/* OBJECT IDENTIFIER */
+	FT_LSPID,
 	FT_NUM_TYPES /* last item number plus one */
 };
 
Index: epan/proto.c
===================================================================
--- epan/proto.c	(révision 20088)
+++ epan/proto.c	(copie de travail)
@@ -142,7 +142,11 @@
 proto_tree_set_ether(field_info *fi, const guint8* value);
 static void
 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
+static void 
+proto_tree_set_lspid(field_info *fi, const guint8 *value);
 static void
+proto_tree_set_lspid_tvb(field_info *fi, tvbuff_t *tvb, gint start);
+static void
 proto_tree_set_ipxnet(field_info *fi, guint32 value);
 static void
 proto_tree_set_ipv4(field_info *fi, guint32 value);
@@ -900,6 +904,11 @@
 			proto_tree_set_ether_tvb(new_fi, tvb, start);
 			break;
 
+		case FT_LSPID:
+			DISSECTOR_ASSERT(length==8);
+			proto_tree_set_lspid_tvb(new_fi, tvb, start);
+			break;
+
 		case FT_GUID:
 			DISSECTOR_ASSERT(length == 16);
 			proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
@@ -1982,6 +1991,30 @@
 	proto_tree_set_string(fi, string, TRUE);
 }
 
+/* Add a FT_LSPID to a proto_tree */
+proto_item *
+proto_tree_add_lspid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+    const guint8* value)
+{
+        proto_item *pi;
+	field_info		*new_fi;
+	header_field_info	*hfinfo;
+
+	if (!tree)
+		return (NULL);
+
+	TRY_TO_FAKE_THIS_ITEM(tree, hfindex);
+
+	PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+	DISSECTOR_ASSERT(hfinfo->type == FT_LSPID);
+
+	pi = proto_tree_add_pi(tree, hfindex, tvb, start, &length, &new_fi);
+	proto_tree_set_lspid(new_fi, value);
+
+	return pi;
+
+}
+
 /* Add a FT_ETHER to a proto_tree */
 proto_item *
 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
@@ -2057,6 +2090,13 @@
 	return pi;
 }
 
+/* Set the FT_LSPID value */
+static void 
+proto_tree_set_lspid(field_info *fi, const guint8* value)
+{
+  fvalue_set(&fi->value, (gpointer) value, FALSE);
+}
+
 /* Set the FT_ETHER value */
 static void
 proto_tree_set_ether(field_info *fi, const guint8* value)
@@ -2065,6 +2105,12 @@
 }
 
 static void
+proto_tree_set_lspid_tvb(field_info *fi, tvbuff_t *tvb, gint start)
+{
+  proto_tree_set_lspid(fi, tvb_get_ptr(tvb, start, 8));
+}
+
+static void
 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
 {
 	proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, 6));
@@ -3834,6 +3880,15 @@
 				label_str[ITEM_LABEL_LENGTH - 1] = '\0';
 			break;
 
+		case FT_LSPID:
+			bytes = fvalue_get(&fi->value);
+			ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+			    "%s: %s", hfinfo->name,
+			    lspid_to_str(bytes));
+			if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
+			  label_str[ITEM_LABEL_LENGTH - 1] = '\0';
+			break;
+
 		case FT_IPv4:
 			ipv4 = fvalue_get(&fi->value);
 			n_addr = ipv4_get_net_order_addr(ipv4);
Index: epan/proto.h
===================================================================
--- epan/proto.h	(révision 20088)
+++ epan/proto.h	(copie de travail)
@@ -773,6 +773,18 @@
 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
 	gint length, const guint8* value_ptr, const char *format, ...) GNUC_FORMAT_CHECK(printf,7,8);
 
+/** Add a FT_LSPID to a proto_tree.
+ @param tree the tree to append this item to
+ @param hfindex field index
+ @param tvb the tv buffer of the current data
+ @param start start of data in tvb
+ @param length length of data in tvb
+ @param value data to display
+ @return the newly created item */
+proto_item *
+proto_tree_add_lspid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
+    const guint8* value);
+
 /** Add a FT_ETHER to a proto_tree.
  @param tree the tree to append this item to
  @param hfindex field index
Index: epan/to_str.c
===================================================================
--- epan/to_str.c	(révision 20088)
+++ epan/to_str.c	(copie de travail)
@@ -140,6 +140,7 @@
   return buf;
 }
 
+
 /*
  This function is very fast and this function is called a lot.
  XXX update the address_to_str stuff to use this function.
@@ -236,6 +237,32 @@
   inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
 }
 
+gchar *
+lspid_to_str(const guint8 *lspid){
+  gchar *cur;
+  guint8 cur_len;
+
+  cur_len = MAX_SYSTEMID_LEN * 3 + 5;
+  cur = ep_alloc(cur_len);
+
+  g_snprintf(cur, cur_len, "%02x%02x.%02x%02x.%02x%02x.%02x-%02x", 
+      lspid[0], lspid[1], lspid[2], lspid[3], 
+      lspid[4], lspid[5], lspid[6], lspid[7]);
+
+  return cur;
+}
+
+void lspid_to_str_buf(const guint8* lspid, gchar *buf)
+{
+  if (buf == NULL)
+    return;
+
+  g_snprintf(buf, MAX_SYSTEMID_LEN * 3 + 5, "%02x%02x.%02x%02x.%02x%02x.%02x-%02x",
+      lspid[0], lspid[1], lspid[2], lspid[3], 
+      lspid[4], lspid[5], lspid[6], lspid[7]);
+}
+
+
 gchar*
 ipx_addr_to_str(guint32 net, const guint8 *ad)
 {
Index: epan/to_str.h
===================================================================
--- epan/to_str.h	(révision 20088)
+++ epan/to_str.h	(copie de travail)
@@ -56,6 +56,8 @@
 extern void     address_to_str_buf(const address *addr, gchar *buf, int buf_len);
 extern gchar*   bytestring_to_str(const guint8 *, guint32, char);
 extern gchar*	ether_to_str(const guint8 *);
+extern gchar*   lspid_to_str(const guint8 *);
+extern void lspid_to_str_buf(const guint8* lspid, gchar *buf);
 extern gchar*	ip_to_str(const guint8 *);
 extern void	ip_to_str_buf(const guint8 *, gchar *);
 extern gchar*	fc_to_str(const guint8 *);