Ethereal-dev: [Ethereal-dev] nettl (HP-UX) - Added HP-PB FDDI support

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

From: "Mark C. Brown" <mbrown@xxxxxxxxxx>
Date: Sat, 02 Oct 2004 18:43:10 -0400
Patch to add support for HP-PB FDDI trace records.

Sorry for the premature patch yesterday, Guy.  I finally
figured out the VERY strange format of these records...

Thanks!

-- 
"If a train station is where a train stops, | Mark C. Brown
 then what's a workstation?" -- D. Huber    | mbrown@xxxxxxxxxx
Index: nettl.c
===================================================================
--- nettl.c	(revision 12185)
+++ nettl.c	(working copy)
@@ -55,12 +55,14 @@
 /* HP nettl record header for the NS_LS_IP subsystem */
 /* This also works for BASE100 and GSC100BT */
 struct nettlrec_ns_ls_ip_hdr {
-    guint8	xxa[28];
+    guint8	xxa[8];
+    guint8	rectype;
+    guint8	xxb[19];
     guint8	caplen[4];
     guint8	length[4];
     guint8	sec[4];
     guint8	usec[4];
-    guint8	xxb[16];
+    guint8	xxc[16];
 };
 
 
@@ -130,9 +132,9 @@
 		int length, int *err, gchar **err_info);
 static int nettl_read_rec_header(wtap *wth, FILE_T fh,
 		struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header,
-		int *err, gchar **err_info);
+		int *err, gchar **err_info, gboolean *fddihack);
 static gboolean nettl_read_rec_data(FILE_T fh, guchar *pd, int length,
-		int *err);
+		int *err, gboolean fddihack);
 static void nettl_close(wtap *wth);
 
 int nettl_open(wtap *wth, int *err, gchar **err_info _U_)
@@ -190,11 +192,12 @@
     long *data_offset)
 {
     int ret;
+    gboolean fddihack=FALSE;
 
     /* Read record header. */
     *data_offset = wth->data_offset;
     ret = nettl_read_rec_header(wth, wth->fh, &wth->phdr, &wth->pseudo_header,
-        err, err_info);
+        err, err_info, &fddihack);
     if (ret <= 0) {
 	/* Read error or EOF */
 	return FALSE;
@@ -221,7 +224,7 @@
      */
     buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
     if (!nettl_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
-		wth->phdr.caplen, err))
+		wth->phdr.caplen, err, fddihack))
 	return FALSE;	/* Read error */
     wth->data_offset += wth->phdr.caplen;
     return TRUE;
@@ -234,13 +237,14 @@
 {
     int ret;
     struct wtap_pkthdr phdr;
+    gboolean fddihack=FALSE;
 
     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
 	return FALSE;
 
     /* Read record header. */
     ret = nettl_read_rec_header(wth, wth->random_fh, &phdr, pseudo_header,
-        err, err_info);
+        err, err_info, &fddihack);
     if (ret <= 0) {
 	/* Read error or EOF */
 	if (ret == 0) {
@@ -253,13 +257,13 @@
     /*
      * Read the packet data.
      */
-    return nettl_read_rec_data(wth->random_fh, pd, length, err);
+    return nettl_read_rec_data(wth->random_fh, pd, length, err, fddihack);
 }
 
 static int
 nettl_read_rec_header(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
 		union wtap_pseudo_header *pseudo_header, int *err,
-		gchar **err_info)
+		gchar **err_info, gboolean *fddihack)
 {
     int bytes_read;
     struct nettlrec_sx25l2_hdr lapb_hdr;
@@ -267,11 +271,13 @@
     struct nettlrec_ns_ls_drv_eth_hdr drv_eth_hdr;
     guint16 length;
     int offset = 0;
-    guint8 encap[4];
+    int encap;
+    int padlen;
     guint8 dummy[4];
+    guchar dummyc[12];
 
     errno = WTAP_ERR_CANT_READ;
-    bytes_read = file_read(encap, 1, 4, fh);
+    bytes_read = file_read(dummy, 1, 4, fh);
     if (bytes_read != 4) {
 	*err = file_error(fh);
 	if (*err != 0)
@@ -283,8 +289,9 @@
 	return 0;
     }
     offset += 4;
+    encap=dummy[3];
 
-    switch (encap[3]) {
+    switch (encap) {
 	case NETTL_SUBSYS_LAN100 :
 	case NETTL_SUBSYS_BASE100 :
 	case NETTL_SUBSYS_GSC100BT :
@@ -295,6 +302,7 @@
 	case NETTL_SUBSYS_INTL100 :
 	case NETTL_SUBSYS_IGELAN :
 	case NETTL_SUBSYS_IETHER :
+	case NETTL_SUBSYS_HPPB_FDDI :
         case NETTL_SUBSYS_PCI_FDDI :
         case NETTL_SUBSYS_TOKEN :
         case NETTL_SUBSYS_PCI_TR :
@@ -307,20 +315,21 @@
 	case NETTL_SUBSYS_NS_LS_IPV6 :
 	case NETTL_SUBSYS_NS_LS_ICMPV6 :
 	case NETTL_SUBSYS_NS_LS_ICMP :
-	    if( (encap[3] == NETTL_SUBSYS_NS_LS_IP)
-	     || (encap[3] == NETTL_SUBSYS_NS_LS_LOOPBACK)
-	     || (encap[3] == NETTL_SUBSYS_NS_LS_UDP)
-	     || (encap[3] == NETTL_SUBSYS_NS_LS_TCP)
-	     || (encap[3] == NETTL_SUBSYS_NS_LS_IPV6)) {
+	    if( (encap == NETTL_SUBSYS_NS_LS_IP)
+	     || (encap == NETTL_SUBSYS_NS_LS_LOOPBACK)
+	     || (encap == NETTL_SUBSYS_NS_LS_UDP)
+	     || (encap == NETTL_SUBSYS_NS_LS_TCP)
+	     || (encap == NETTL_SUBSYS_NS_LS_IPV6)) {
 		phdr->pkt_encap = WTAP_ENCAP_RAW_IP;
-	    } else if (encap[3] == NETTL_SUBSYS_NS_LS_ICMP) {
+	    } else if (encap == NETTL_SUBSYS_NS_LS_ICMP) {
 		phdr->pkt_encap = WTAP_ENCAP_RAW_ICMP;
-	    } else if (encap[3] == NETTL_SUBSYS_NS_LS_ICMPV6) {
+	    } else if (encap == NETTL_SUBSYS_NS_LS_ICMPV6) {
 		phdr->pkt_encap = WTAP_ENCAP_RAW_ICMPV6;
-	    } else if (encap[3] == NETTL_SUBSYS_PCI_FDDI) {
+	    } else if( (encap == NETTL_SUBSYS_HPPB_FDDI)
+		    || (encap == NETTL_SUBSYS_PCI_FDDI) ) {
 		phdr->pkt_encap = WTAP_ENCAP_FDDI;
-	    } else if( (encap[3] == NETTL_SUBSYS_PCI_TR)
-		    || (encap[3] == NETTL_SUBSYS_TOKEN) ) {
+	    } else if( (encap == NETTL_SUBSYS_PCI_TR)
+		    || (encap == NETTL_SUBSYS_TOKEN) ) {
 		phdr->pkt_encap = WTAP_ENCAP_TOKEN_RING;
 	    } else {
 		phdr->pkt_encap = WTAP_ENCAP_ETHERNET;
@@ -358,8 +367,57 @@
 		offset += 4;
 	    }
 
-	    /* PCI FDDI has an extra 3 bytes of padding */
-	    if (encap[3] == NETTL_SUBSYS_PCI_FDDI) {
+	    /* HPPB FDDI has different inbound vs outbound trace records */
+	    if (encap == NETTL_SUBSYS_HPPB_FDDI) {
+                if (ip_hdr.rectype == NETTL_HDR_PDUIN) {
+                   /* inbound is very strange...
+                      there are an extra 3 bytes after the DSAP and SSAP
+                      for SNAP frames ???
+                   */
+                   *fddihack=TRUE;
+		   length = pntohl(&ip_hdr.length);
+		   if (length <= 0)
+		       return 0;
+		   phdr->len = length;
+		   length = pntohl(&ip_hdr.caplen);
+		   phdr->caplen = length;
+                } else {
+	           /* outbound has an extra padding */
+		   bytes_read = file_read(dummyc, 1, 9, fh);
+		   if (bytes_read != 9) {
+		       *err = file_error(fh);
+		       if (*err != 0)
+			   return -1;
+		       if (bytes_read != 0) {
+			   *err = WTAP_ERR_SHORT_READ;
+			   return -1;
+		       }
+		       return 0;
+		   }
+                   /* padding is usually either a total 11 or 16 bytes??? */
+		   padlen = (int)dummyc[8];
+		   bytes_read = file_read(dummy, 1, padlen, fh);
+		   if (bytes_read != padlen) {
+		       *err = file_error(fh);
+		       if (*err != 0)
+			   return -1;
+		       if (bytes_read != 0) {
+			   *err = WTAP_ERR_SHORT_READ;
+			   return -1;
+		       }
+		       return 0;
+		   }
+		   padlen += 9;
+		   offset += padlen;
+		   length = pntohl(&ip_hdr.length);
+		   if (length <= 0)
+			   return 0;
+		   phdr->len = length - padlen;
+		   length = pntohl(&ip_hdr.caplen);
+		   phdr->caplen = length - padlen;
+               }
+	    } else if (encap == NETTL_SUBSYS_PCI_FDDI) {
+	        /* PCI FDDI has an extra 3 bytes of padding */
 		bytes_read = file_read(dummy, 1, 3, fh);
 		if (bytes_read != 3) {
 		    *err = file_error(fh);
@@ -378,7 +436,7 @@
 		phdr->len = length - 3;
 		length = pntohl(&ip_hdr.caplen);
 		phdr->caplen = length - 3;
-	    } else if (encap[3] == NETTL_SUBSYS_NS_LS_LOOPBACK) {
+	    } else if (encap == NETTL_SUBSYS_NS_LS_LOOPBACK) {
 	        /* LOOPBACK has an extra 26 bytes of padding */
 		bytes_read = file_read(dummy, 1, 26, fh);
 		if (bytes_read != 26) {
@@ -509,29 +567,44 @@
 	    pseudo_header->x25.flags =
 		(lapb_hdr.from_dce & 0x20 ? FROM_DCE : 0x00);
 	    break;
-	case NETTL_SUBSYS_HPPB_FDDI :
-	    /* HP-PB FDDI has a different trace records for inbound vs outbound
-               Still need to work out a way 'round that...
-            */
-	    *err = WTAP_ERR_UNSUPPORTED_ENCAP;
-	    *err_info = g_strdup_printf("nettl: HP-PB FDDI [Subsystem %u] currently unsupported",
-		    encap[3]);
-	    return -1;
 	default:
 	    *err = WTAP_ERR_UNSUPPORTED_ENCAP;
 	    *err_info = g_strdup_printf("nettl: subsystem %u unknown or unsupported",
-		    encap[3]);
+		    encap);
 	    return -1;
     }
     return offset;
 }
 
 static gboolean
-nettl_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
+nettl_read_rec_data(FILE_T fh, guchar *pd, int length, int *err, gboolean fddihack)
 {
     int bytes_read;
+    guchar *p=NULL;
+    guint8 dummy[3];
 
-    bytes_read = file_read(pd, 1, length, fh);
+    if (fddihack == TRUE) {
+       /* read in FC, dest, src and DSAP */
+       if (file_read(pd, 1, 14, fh) == 14) {
+          if (pd[13] == 0xAA) {
+             /* it's SNAP, have to eat 3 bytes??? */
+             if (file_read(dummy, 1, 3, fh) == 3) {
+                p=pd+14;
+                bytes_read = file_read(p, 1, length-17, fh);
+                bytes_read += 17;
+             } else {
+                bytes_read = -1;
+             }
+          } else {
+             /* not SNAP */
+             p=pd+14;
+             bytes_read = file_read(p, 1, length-14, fh);
+             bytes_read += 14;
+          }
+       } else
+          bytes_read = -1;
+    } else
+       bytes_read = file_read(pd, 1, length, fh);
 
     if (bytes_read != length) {
 	*err = file_error(fh);
Index: nettl.h
===================================================================
--- nettl.h	(revision 12185)
+++ nettl.h	(working copy)
@@ -94,6 +94,11 @@
 #define NETTL_SUBSYS_TOKEN		31
 #define NETTL_SUBSYS_PCI_TR		187
 
+/* from /usr/include/sys/subsys_id.h */
+
+#define NETTL_HDR_PDUIN			0x20
+#define NETTL_HDR_PDUOUT		0x10
+
 int nettl_open(wtap *wth, int *err, gchar **err_info);
 
 #endif