Ethereal-dev: [ethereal-dev] patch for X.25 dissector and nettl file format

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

From: Olivier Abad <abad@xxxxxxxxxxxxx>
Date: Sun, 17 Oct 1999 21:23:56 +0200
Hi,

Here is a new patch. It adds :
- more display filters for X.25
- no LCN in RESTART / DIAGNOSTIC / REGISTRATION packets
- support for nettl file format (nettl is a trace tool for HP-UX). For
now, it only supports traces for X.25 interfaces (tested with HP-UX
10.20).

Olivier


diff -Nru ethereal/packet-x25.c ethereal.local/packet-x25.c
--- ethereal/packet-x25.c	Tue Oct 12 18:28:35 1999
+++ ethereal.local/packet-x25.c	Sun Oct 17 21:11:36 1999
@@ -85,8 +85,50 @@
 #define X25_FAC_CALL_DEFLECT		0xD1
 
 int proto_x25 = -1;
+int hf_x25_qbit = -1;
+int hf_x25_dbit = -1;
+int hf_x25_mod = -1;
 int hf_x25_lcn = -1;
 int hf_x25_type = -1;
+int hf_x25_p_r = -1;
+int hf_x25_mbit = -1;
+int hf_x25_p_s = -1;
+int proto_ex25 = -1;
+int hf_ex25_qbit = -1;
+int hf_ex25_dbit = -1;
+int hf_ex25_mod = -1;
+int hf_ex25_lcn = -1;
+int hf_ex25_type = -1;
+int hf_ex25_p_r = -1;
+int hf_ex25_mbit = -1;
+int hf_ex25_p_s = -1;
+
+static const value_string vals_modulo[] = {
+	{ 1, "8" },
+	{ 2, "128" },
+	{ 0, NULL}
+};
+
+static const value_string vals_x25_type[] = {
+	{ X25_CALL_REQUEST, "Call" },
+	{ X25_CALL_ACCEPTED, "Call Accepted" },
+	{ X25_CLEAR_REQUEST, "Clear" },
+	{ X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
+	{ X25_INTERRUPT, "Interrupt" },
+	{ X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
+	{ X25_RESET_REQUEST, "Reset" },
+	{ X25_RESET_CONFIRMATION, "Reset Confirmation" },
+	{ X25_RESTART_REQUEST, "Restart" },
+	{ X25_RESTART_CONFIRMATION, "Restart Confirmation" },
+	{ X25_REGISTRATION_REQUEST, "Registration" },
+	{ X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
+	{ X25_DIAGNOSTIC, "Diagnostic" },
+	{ X25_RR, "RR" },
+	{ X25_RNR, "RNR" },
+	{ X25_REJ, "REJ" },
+	{ X25_DATA, "DATA" },
+	{ 0,   NULL}
+};
 
 /*
  * each vc_info node contains :
@@ -1017,41 +1059,44 @@
 	if (check_col(fd, COL_INFO))
 	    col_add_str(fd, COL_INFO, "Invalid/short X.25 packet");
 	if (tree)
-	    proto_tree_add_item_format(tree, proto_x25, localoffset,
-		    fd->cap_len - offset, NULL, "Invalid/short X.25 packet");
+	    proto_tree_add_item_format(tree, (modulo == 8 ? proto_x25 : proto_ex25),
+			    localoffset, fd->cap_len - offset, NULL,
+			    "Invalid/short X.25 packet");
 	return;
     }
-    vc = (int)(pd[localoffset] & 0x0F) + (int)pd[localoffset+1];
+    vc = (int)(pd[localoffset] & 0x0F)*256 + (int)pd[localoffset+1];
     if (tree) {
-	ti = proto_tree_add_item(tree, proto_x25, localoffset, x25_pkt_len,
-				 NULL);
+	ti = proto_tree_add_item(tree, (modulo == 8) ? proto_x25 : proto_ex25,
+		localoffset, x25_pkt_len, NULL);
 	x25_tree = proto_item_add_subtree(ti, ETT_X25);
-	proto_tree_add_text(x25_tree, localoffset, 1,
-			    "GFI : Q: %d, D: %d, Mod: %d",
-			    (pd[localoffset] & 0x80) ? 1 : 0,
-			    (pd[localoffset] & 0x40) ? 1 : 0,
-			    modulo);
-	proto_tree_add_item_format(x25_tree, hf_x25_lcn, localoffset, 2,
-				   (int)(pd[localoffset] & 0x0F) +
-				   (int)pd[localoffset+1],
-				   "Logical channel : %3.3X",
-				   vc);
+	if (pd[localoffset] & 0x80)
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_qbit : hf_ex25_qbit,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	if (pd[localoffset] & 0x40)
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_dbit : hf_ex25_dbit,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_mod : hf_ex25_mod,
+		localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
     }
     switch (pd[localoffset+2]) {
     case X25_CALL_REQUEST:
 	if (pd[localoffset+2] & 0x80) /* TOA/NPI address format */
 	    toa = TRUE;
 
-	if(check_col(fd, COL_INFO))
+	if (check_col(fd, COL_INFO))
 	    col_add_fstr(fd, COL_INFO, "%s VC:%d",
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Inc. call"
 		                                             : "Call req." ,
                     vc);
-	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-		    "CALL",
+	if (x25_tree) {
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item_format(x25_tree,
+		    (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_CALL_REQUEST,
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Incoming call"
 			                                     : "Call request");
+	}
 	localoffset += 3;
 	if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
 	    x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
@@ -1099,11 +1144,15 @@
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call conn."
 			                                     : "Call acc." ,
 		    vc);
-	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-		    "CALL ACC",
+	if (x25_tree) {
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item_format(x25_tree,
+		    (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_CALL_ACCEPTED,
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Call connected"
 		                                             : "Call accepted");
+	}
 	localoffset += 3;
         if (localoffset < x25_pkt_len+offset) /* calling/called addresses */
 	    x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, toa);
@@ -1128,8 +1177,11 @@
 	}
 	x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
 	if (x25_tree) {
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-		    "CLEAR",
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item_format(x25_tree,
+		    (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_CLEAR_REQUEST,
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Clear indication"
 		                                             : "Clear request");
 	    if (localoffset+3 < x25_pkt_len+offset)
@@ -1148,9 +1200,12 @@
 
 	if(check_col(fd, COL_INFO))
 	    col_add_fstr(fd, COL_INFO, "Clear Conf. VC:%d", vc);
-	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "CLEAR CONF", "Clear confirmation");
+	if (x25_tree) {
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_CLEAR_CONFIRMATION);
+	}
 	localoffset += x25_pkt_len;
 
 	if (localoffset < fd->cap_len) /* extended clear conf format */
@@ -1161,12 +1216,11 @@
 	break;
     case X25_DIAGNOSTIC:
 	if(check_col(fd, COL_INFO)) {
-	    col_add_fstr(fd, COL_INFO, "Diag. VC:%d %d",
-		    vc, (int)pd[localoffset+3]);
+	    col_add_fstr(fd, COL_INFO, "Diag. %d", (int)pd[localoffset+3]);
 	}
 	if (x25_tree) {
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "DIAG", "Diagnostic");
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_DIAGNOSTIC);
 	    if (localoffset+3 < x25_pkt_len+offset)
 		proto_tree_add_text(x25_tree, localoffset+3, 1,
 			"Diagnostic : %d", (int)pd[localoffset+3]);
@@ -1176,17 +1230,23 @@
     case X25_INTERRUPT:
 	if(check_col(fd, COL_INFO))
 	    col_add_fstr(fd, COL_INFO, "Interrupt VC:%d", vc);
-	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "INTR", "Interrupt");
+	if (x25_tree) {
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_INTERRUPT);
+	}
 	localoffset += x25_pkt_len;
 	break;
     case X25_INTERRUPT_CONFIRMATION:
 	if(check_col(fd, COL_INFO))
 	    col_add_fstr(fd, COL_INFO, "Interrupt Conf. VC:%d", vc);
-	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "INTR CONF", "Interrupt confirmation");
+	if (x25_tree) {
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_INTERRUPT_CONFIRMATION);
+	}
 	localoffset += x25_pkt_len;
 	break;
     case X25_RESET_REQUEST:
@@ -1199,8 +1259,11 @@
 	}
 	x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
 	if (x25_tree) {
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-		    "RESET",
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item_format(x25_tree,
+		    (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
+		    X25_RESET_REQUEST,
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Reset indication"
                                                              : "Reset request");
 	    if (localoffset+3 < x25_pkt_len+offset)
@@ -1215,23 +1278,26 @@
     case X25_RESET_CONFIRMATION:
 	if(check_col(fd, COL_INFO))
 	    col_add_fstr(fd, COL_INFO, "Reset conf. VC:%d", vc);
-	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "RESET CONF", "Reset confirmation");
+	if (x25_tree) {
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+		    localoffset, 2, pd[localoffset]*256+pd[localoffset+1]);
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_RESET_CONFIRMATION);
+	}
 	localoffset += x25_pkt_len;
 	break;
     case X25_RESTART_REQUEST:
 	if(check_col(fd, COL_INFO)) {
-	    col_add_fstr(fd, COL_INFO, "%s VC:%d %s - Diag.:%d",
+	    col_add_fstr(fd, COL_INFO, "%s %s - Diag.:%d",
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart ind."
 		                                             : "Restart req.",
-		    vc, restart_code(pd[localoffset+3]),
+		    restart_code(pd[localoffset+3]),
 		    (int)pd[localoffset+4]);
 	}
-	x25_hash_add_proto_end(vc, fd->abs_secs, fd->abs_usecs);
 	if (x25_tree) {
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-		    "RESTART",
+	    proto_tree_add_item_format(x25_tree,
+		    (modulo == 8) ? hf_x25_type : hf_ex25_type, localoffset+2, 1,
+		    X25_RESTART_REQUEST,
 		    (fd->pseudo_header.x25.flags & FROM_DCE) ? "Restart indication"
 		                                             : "Restart request");
 	    if (localoffset+3 < x25_pkt_len+offset)
@@ -1245,18 +1311,18 @@
 	break;
     case X25_RESTART_CONFIRMATION:
 	if(check_col(fd, COL_INFO))
-	    col_add_fstr(fd, COL_INFO, "Restart conf. VC:%d", vc);
+	    col_add_str(fd, COL_INFO, "Restart conf.");
 	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "RESTART CONF", "Restart confirmation");
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_RESTART_CONFIRMATION);
 	localoffset += x25_pkt_len;
 	break;
     case X25_REGISTRATION_REQUEST:
 	if(check_col(fd, COL_INFO))
-	    col_add_fstr(fd, COL_INFO, "Registration req. VC:%d", vc);
+	    col_add_str(fd, COL_INFO, "Registration req.");
 	if (x25_tree)
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "REG REQ", "Registration request");
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_REGISTRATION_REQUEST);
 	localoffset += 3;
 	if (localoffset < x25_pkt_len+offset)
 	    x25_ntoa(x25_tree, &localoffset, &pd[localoffset], fd, FALSE);
@@ -1273,10 +1339,10 @@
 	break;
     case X25_REGISTRATION_CONFIRMATION:
 	if(check_col(fd, COL_INFO))
-	    col_add_fstr(fd, COL_INFO, "Registration conf. VC:%d", vc);
+	    col_add_str(fd, COL_INFO, "Registration conf.");
 	if (x25_tree) {
-	    proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset+2, 1,
-				       "REG CONF", "Registration confirmation");
+	    proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_type : hf_ex25_type,
+		    localoffset+2, 1, X25_REGISTRATION_CONFIRMATION);
 	    if (localoffset+3 < x25_pkt_len+offset)
 		proto_tree_add_text(x25_tree, localoffset+3, 1,
 			"Cause: %s", registration_code(pd[localoffset+3]));
@@ -1317,41 +1383,32 @@
 			    (pd[localoffset+1] & 0x01) ? " M" : "");
 	    }
 	    if (x25_tree) {
-		proto_tree_add_item_format(x25_tree, hf_x25_type, localoffset,
-					   1, "DATA", "X.25 Data");
+		proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+			localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
 		if (modulo == 8) {
+		    proto_tree_add_item_hidden(x25_tree, hf_x25_type, localoffset, 1,
+			    X25_DATA);
+		    proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
+			    pd[localoffset]);
+		    if (pd[localoffset] & 0x10)
+			proto_tree_add_item(x25_tree, hf_x25_mbit, localoffset, 1,
+			    pd[localoffset]);
+		    proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset, 1,
+			    pd[localoffset]);
 		    proto_tree_add_text(x25_tree, localoffset, 1,
-			    "          %d%d%d..... : P(R) = %d",
-			    (pd[localoffset] >> 7) & 0x01,
-			    (pd[localoffset] >> 6) & 0x01,
-			    (pd[localoffset] >> 5) & 0x01,
-			    (pd[localoffset] >> 5) & 0x07);
-		    proto_tree_add_text(x25_tree, localoffset, 1,
-			    "          ...%d.... : More bit",
-			    (pd[localoffset] >> 4) & 0x01);
-		    proto_tree_add_text(x25_tree, localoffset, 1,
-			    "          ....%d%d%d. : P(S) = %d",
-			    (pd[localoffset] >> 3) & 0x01,
-			    (pd[localoffset] >> 2) & 0x01,
-			    (pd[localoffset] >> 1) & 0x01,
-			    (pd[localoffset] >> 1) & 0x07);
-		    proto_tree_add_text(x25_tree, localoffset, 1,
-			    "          .......0 : Packet type id = DATA");
+			    decode_boolean_bitfield(pd[localoffset], 0x01, 1*8,
+				NULL, "DATA"));
 		}
 		else {
-		    proto_tree_add_text(x25_tree, localoffset+1, 1,
-			    "          %d%d%d%d%d%d%d. : P(S) = %d",
-			    (pd[localoffset+1] >> 7) & 0x01,
-			    (pd[localoffset+1] >> 6) & 0x01,
-			    (pd[localoffset+1] >> 5) & 0x01,
-			    (pd[localoffset+1] >> 4) & 0x01,
-			    (pd[localoffset+1] >> 3) & 0x01,
-			    (pd[localoffset+1] >> 2) & 0x01,
-			    (pd[localoffset+1] >> 1) & 0x01,
-			    pd[localoffset+1] >> 1);
-		    proto_tree_add_text(x25_tree, localoffset, 1,
-			    "          .......%d : More bit",
-			    pd[localoffset+1] & 0x01);
+		    proto_tree_add_item_hidden(x25_tree, hf_ex25_type, localoffset, 1,
+			    X25_DATA);
+		    proto_tree_add_item(x25_tree, hf_x25_p_r, localoffset, 1,
+			    pd[localoffset]);
+		    proto_tree_add_item(x25_tree, hf_x25_p_s, localoffset+1, 1,
+			    pd[localoffset+1]);
+		    if (pd[localoffset+1] & 0x01)
+			proto_tree_add_item(x25_tree, hf_ex25_mbit, localoffset+1, 1,
+			    pd[localoffset+1]);
 		}
 	    }
 	    localoffset += (modulo == 8) ? 1 : 2;
@@ -1369,14 +1426,18 @@
 			    vc, pd[localoffset+1] >> 1);
 	    }
 	    if (x25_tree) {
-		if (modulo == 8)
-		    proto_tree_add_item_format(x25_tree, hf_x25_type,
-			    localoffset, 1, "RR", "RR P(R):%d",
-			    (pd[localoffset] >> 5) & 0x07);
-		else
-		    proto_tree_add_item_format(x25_tree, hf_x25_type,
-			    localoffset, 2, "RR", "RR P(R):%d",
-			    pd[localoffset+1] >> 1);
+		proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+			localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
+		if (modulo == 8) {
+		    proto_tree_add_item(x25_tree, hf_x25_p_r,
+			    localoffset, 1, pd[localoffset]);
+		    proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RR);
+		}
+		else {
+		    proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RR);
+		    proto_tree_add_item(x25_tree, hf_ex25_p_r,
+			    localoffset+1, 1, pd[localoffset+1]);
+		}
 	    }
 	    break;
 
@@ -1390,14 +1451,18 @@
 			    vc, pd[localoffset+1] >> 1);
 	    }
 	    if (x25_tree) {
-		if (modulo == 8)
-		    proto_tree_add_item_format(x25_tree, hf_x25_type,
-			    localoffset, 1, "RNR", "RNR P(R):%d",
-			    (pd[localoffset] >> 5) & 0x07);
-		else
-		    proto_tree_add_item_format(x25_tree, hf_x25_type,
-			    localoffset, 2, "RNR", "RNR P(R):%d",
-			    pd[localoffset+1] >> 1);
+		proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+			localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
+		if (modulo == 8) {
+		    proto_tree_add_item(x25_tree, hf_x25_p_r,
+			    localoffset, 1, pd[localoffset]);
+		    proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_RNR);
+		}
+		else {
+		    proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_RNR);
+		    proto_tree_add_item(x25_tree, hf_ex25_p_r,
+			    localoffset+1, 1, pd[localoffset+1]);
+		}
 	    }
 	    break;
 
@@ -1411,14 +1476,18 @@
 			    vc, pd[localoffset+1] >> 1);
 	    }
 	    if (x25_tree) {
-		if (modulo == 8)
-		    proto_tree_add_item_format(x25_tree, hf_x25_type,
-			    localoffset, 1, "REJ", "REJ P(R):%d",
-			    (pd[localoffset] >> 5) & 0x07);
-		else
-		    proto_tree_add_item_format(x25_tree, hf_x25_type,
-			    localoffset, 2, "REJ", "REJ P(R):%d",
-			    pd[localoffset+1] >> 1);
+		proto_tree_add_item(x25_tree, (modulo == 8) ? hf_x25_lcn : hf_ex25_lcn,
+			localoffset-2, 2, pd[localoffset-2]*256+pd[localoffset-1]);
+		if (modulo == 8) {
+		    proto_tree_add_item(x25_tree, hf_x25_p_r,
+			    localoffset, 1, pd[localoffset]);
+		    proto_tree_add_item(x25_tree, hf_x25_type, localoffset, 1, X25_REJ);
+		}
+		else {
+		    proto_tree_add_item(x25_tree, hf_ex25_type, localoffset, 1, X25_REJ);
+		    proto_tree_add_item(x25_tree, hf_ex25_p_r,
+			    localoffset+1, 1, pd[localoffset+1]);
+		}
 	    }
 	}
 	localoffset += (modulo == 8) ? 1 : 2;
@@ -1446,16 +1515,62 @@
 void
 proto_register_x25(void)
 {
-    static hf_register_info hf[] = {
+    static hf_register_info hf8[] = {
+	{ &hf_x25_qbit,
+	  { "Q Bit", "x25.q", FT_BOOLEAN, 2, NULL, 0x8000,
+	  	"Qualifier Bit" } },
+	{ &hf_x25_qbit,
+	  { "D Bit", "x25.d", FT_BOOLEAN, 2, NULL, 0x4000,
+	  	"Delivery Confirmation Bit" } },
+	{ &hf_x25_mod,
+	  { "Modulo", "x25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
+	  	"Specifies whether the frame is modulo 8 or 128" } },
 	{ &hf_x25_lcn,
-	  { "Logical Channel", "x25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0,
-	  	"" } },
-
+	  { "Logical Channel", "x25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
+	  	"Logical Channel Number" } },
 	{ &hf_x25_type,
-	  { "Packet Type", "x25.type", FT_STRING, BASE_NONE, NULL, 0x0,
-	  	"" } },
+	  { "Packet Type", "x25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
+	  	"Packet Type" } },
+	{ &hf_x25_p_r,
+	  { "P(R)", "x25.p_r", FT_UINT8, BASE_HEX, NULL, 0xE0,
+	  	"Packet Receive Sequence Number" } },
+	{ &hf_x25_mbit,
+	  { "M Bit", "x25.m", FT_BOOLEAN, 1, NULL, 0x10,
+	  	"More Bit" } },
+	{ &hf_x25_p_s,
+	  { "P(S)", "x25.p_s", FT_UINT8, BASE_HEX, NULL, 0x0E,
+	  	"Packet Send Sequence Number" } },
+    };
+
+    static hf_register_info hf128[] = {
+	{ &hf_ex25_qbit,
+	  { "Q Bit", "ex25.q", FT_BOOLEAN, 2, NULL, 0x8000,
+	  	"Qualifier Bit" } },
+	{ &hf_ex25_qbit,
+	  { "D Bit", "ex25.d", FT_BOOLEAN, 2, NULL, 0x4000,
+	  	"Delivery Confirmation Bit" } },
+	{ &hf_ex25_mod,
+	  { "Modulo", "ex25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
+	  	"Specifies whether the frame is modulo 8 or 128" } },
+	{ &hf_ex25_lcn,
+	  { "Logical Channel", "ex25.lcn", FT_UINT16, BASE_HEX, NULL, 0x0FFF,
+	  	"Logical Channel Number" } },
+	{ &hf_ex25_type,
+	  { "Packet Type", "ex25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
+	  	"Packet Type" } },
+	{ &hf_ex25_p_r,
+	  { "P(R)", "ex25.p_r", FT_UINT8, BASE_HEX, NULL, 0xFE,
+	  	"Packet Receive Sequence Number" } },
+	{ &hf_ex25_mbit,
+	  { "M Bit", "ex25.m", FT_BOOLEAN, 1, NULL, 0x01,
+	  	"More Bit" } },
+	{ &hf_ex25_p_s,
+	  { "P(S)", "ex25.p_s", FT_UINT8, BASE_HEX, NULL, 0xFE,
+	  	"Packet Send Sequence Number" } },
     };
 
     proto_x25 = proto_register_protocol ("X.25", "x25");
-    proto_register_field_array (proto_x25, hf, array_length(hf));
+    proto_ex25 = proto_register_protocol ("Extended X.25 (modulo 128)", "ex25");
+    proto_register_field_array (proto_x25, hf8, array_length(hf8));
+    proto_register_field_array (proto_ex25, hf128, array_length(hf128));
 }
diff -Nru ethereal/wiretap/Makefile.am ethereal.local/wiretap/Makefile.am
--- ethereal/wiretap/Makefile.am	Sat Oct  9 15:46:53 1999
+++ ethereal.local/wiretap/Makefile.am	Sun Oct 17 21:11:43 1999
@@ -48,6 +48,8 @@
 	libpcap.h		\
 	netmon.c		\
 	netmon.h		\
+	nettl.c			\
+	nettl.h			\
 	netxray.c		\
 	netxray.h		\
 	ngsniffer.c		\
diff -Nru ethereal/wiretap/file.c ethereal.local/wiretap/file.c
--- ethereal/wiretap/file.c	Tue Oct  5 23:26:09 1999
+++ ethereal.local/wiretap/file.c	Sun Oct 17 21:11:43 1999
@@ -36,6 +36,7 @@
 #include "ngsniffer.h"
 #include "radcom.h"
 #include "ascend.h"
+#include "nettl.h"
 #include "libpcap.h"
 #include "snoop.h"
 #include "iptrace.h"
@@ -68,7 +69,8 @@
 	netmon_open,
 	netxray_open,
 	radcom_open,
-	ascend_open
+	ascend_open,
+	nettl_open
 };
 
 int wtap_def_seek_read (FILE *fh, int seek_off, guint8 *pd, int len)
diff -Nru ethereal/wiretap/nettl.c ethereal.local/wiretap/nettl.c
--- ethereal/wiretap/nettl.c	Thu Jan  1 01:00:00 1970
+++ ethereal.local/wiretap/nettl.c	Sun Oct 17 21:11:52 1999
@@ -0,0 +1,147 @@
+/* nettl.c
+ *
+ * Wiretap Library
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxxxxxxxxxxx>
+ * 
+ * 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.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include "wtap.h"
+#include "file.h"
+#include "buffer.h"
+#include "nettl.h"
+
+static char nettl_magic[5] = {
+    0x54, 0x52, 0x00, 0x64, 0x00
+};
+
+/* HP nettl record header - The FCS is not included in the file. */
+struct nettlrec_hdr {
+    char	xxa[12];
+    char	from_dce;
+    char	xxb[55];
+    guint16	length;
+    guint16	length2;    /* don't know which one is captured length / real length */
+    char	xxc[4];
+    char	sec[4];
+    char	usec[4];
+    char	xxd[4];
+};
+
+/* header is followed by data and once again the total length (2 bytes) ! */
+
+static int nettl_read(wtap *wth, int *err);
+
+int nettl_open(wtap *wth, int *err)
+{
+    char magic[5];
+    int bytes_read;
+
+    /* Read in the string that should be at the start of a HP file */
+    file_seek(wth->fh, 0, SEEK_SET);
+    errno = WTAP_ERR_CANT_READ;
+    bytes_read = file_read(magic, 1, 5, wth->fh);
+    if (bytes_read != 5) {
+	if (file_error(wth->fh)) {
+	    *err = errno;
+	    return -1;
+	}
+	return 0;
+    }
+
+    if (memcmp(magic, nettl_magic, 5)) {
+	return 0;
+    }
+
+    file_seek(wth->fh, 0x80, SEEK_SET);
+    wth->data_offset = 0x80;
+
+    /* This is an nettl file */
+    wth->file_type = WTAP_FILE_NETTL;
+    wth->capture.nettl = g_malloc(sizeof(nettl_t));
+    wth->subtype_read = nettl_read;
+    wth->snapshot_length = 16384;	/* not available in header, only in frame */
+
+    wth->capture.nettl->start = 0;
+
+    wth->file_encap = WTAP_ENCAP_LAPB;
+
+    return 1;
+}
+
+/* Read the next packet */
+static int nettl_read(wtap *wth, int *err)
+{
+    int	bytes_read;
+    struct nettlrec_hdr hdr;
+    guint16 length;
+    int	data_offset;
+
+    /* Read record header. */
+    errno = WTAP_ERR_CANT_READ;
+    bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
+    if (bytes_read != sizeof hdr) {
+	if (file_error(wth->fh)) {
+	    *err = errno;
+	    return -1;
+	}
+	if (bytes_read != 0) {
+	    *err = WTAP_ERR_SHORT_READ;
+	    return -1;
+	}
+	return 0;
+    }
+    wth->data_offset += sizeof hdr;
+    length = pntohs(&hdr.length);
+    if (length <= 0) return 0;
+
+    wth->phdr.len = length;
+    wth->phdr.caplen = length;
+
+    wth->phdr.ts.tv_sec = pntohl(&hdr.sec);
+    wth->phdr.ts.tv_usec = pntohl(&hdr.usec);
+    if (wth->capture.nettl->start == 0)
+	wth->capture.nettl->start = wth->phdr.ts.tv_sec;
+    wth->phdr.pseudo_header.x25.flags = (hdr.from_dce & 0x20 ? 0x80 : 0x00);
+
+    /*
+     * Read the packet data.
+     */
+    buffer_assure_space(wth->frame_buffer, length);
+    data_offset = wth->data_offset;
+    errno = WTAP_ERR_CANT_READ;
+    bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
+	    length, wth->fh);
+
+    if (bytes_read != length) {
+	if (file_error(wth->fh))
+	    *err = errno;
+	else
+	    *err = WTAP_ERR_SHORT_READ;
+	return -1;
+    }
+    wth->data_offset += length;
+
+    wth->phdr.pkt_encap = wth->file_encap;
+
+    return data_offset;
+}
diff -Nru ethereal/wiretap/nettl.h ethereal.local/wiretap/nettl.h
--- ethereal/wiretap/nettl.h	Thu Jan  1 01:00:00 1970
+++ ethereal.local/wiretap/nettl.h	Sun Oct 17 21:11:52 1999
@@ -0,0 +1,22 @@
+/* nettl.h
+ *
+ * Wiretap Library
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxxxxxxxxxxx>
+ * 
+ * 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.
+ *
+ */
+
+int nettl_open(wtap *wth, int *err);
diff -Nru ethereal/wiretap/wtap.c ethereal.local/wiretap/wtap.c
--- ethereal/wiretap/wtap.c	Thu Oct  7 20:29:50 1999
+++ ethereal.local/wiretap/wtap.c	Sun Oct 17 21:11:43 1999
@@ -98,6 +98,9 @@
 		case WTAP_FILE_ASCEND:
 			return "Lucent/Ascend access server trace";
 
+		case WTAP_FILE_NETTL:
+			return "HP-UX nettl traces";
+
 		default:
 			g_error("Unknown capture file type %d", wth->file_type);
 			return NULL;
@@ -182,6 +185,10 @@
 
 		case WTAP_FILE_ASCEND:
 			g_free(wth->capture.ascend);
+			break;
+
+		case WTAP_FILE_NETTL:
+			g_free(wth->capture.nettl);
 			break;
 
 		/* default:
diff -Nru ethereal/wiretap/wtap.h ethereal.local/wiretap/wtap.h
--- ethereal/wiretap/wtap.h	Thu Oct  7 20:29:51 1999
+++ ethereal.local/wiretap/wtap.h	Sun Oct 17 21:11:43 1999
@@ -93,7 +93,7 @@
 #define WTAP_ENCAP_ASCEND				14
 
 /* last WTAP_ENCAP_ value + 1 */
-#define WTAP_NUM_ENCAP_TYPES			15
+#define WTAP_NUM_ENCAP_TYPES			16
 
 /* File types that can be read by wiretap.
    We may eventually support writing some or all of these file types,
@@ -112,6 +112,7 @@
 #define WTAP_FILE_NETXRAY_2_001			12
 #define WTAP_FILE_RADCOM			13
 #define WTAP_FILE_ASCEND			14
+#define WTAP_FILE_NETTL				15
 
 /*
  * Maximum packet size we'll support.
@@ -150,6 +151,10 @@
 
 typedef struct {
 	time_t	start;
+} nettl_t;
+
+typedef struct {
+	time_t	start;
 } lanalyzer_t;
 
 typedef struct {
@@ -305,6 +310,7 @@
 		lanalyzer_t		*lanalyzer;
 		ngsniffer_t		*ngsniffer;
 		radcom_t		*radcom;
+		nettl_t			*nettl;
 		netmon_t		*netmon;
 		netxray_t		*netxray;
 		ascend_t		*ascend;


-- 
There's such a thing as too much point on a pencil.
		-- H. Allen Smith, "Let the Crabgrass Grow"