Ethereal-dev: [ethereal-dev] TCP/UDP protcol dissector lookups

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

From: Jeff Foster <jfoste@xxxxxxxxxxxx>
Date: Tue, 22 Feb 2000 15:32:10 -0600
I have worked up the attached code as a lookup routine for the TCP and UPD 
port based dissectors. Please review it and make comments.

It is an array of link lists.  The port number is used to index into the
array and then the link list is searched for the first dissector that 
matches the port number.  I think it has some nice features -

1) Allow a second protocol to be installed in place of standard protocol.
	ie) A computer is setup with ssh instead of telnet on port 21, 
		then the ssh protocol could be added in place of telnet
protocol.

2) A protocol can be removed from the list.

3) Lookup speed will be better than a link list.  Although not as good as
a hash; but a hash list won't allow adding and removing a protocol without
destorying any other protocol that used that port.


This design would allow ethereal to move toward installable modules for all
the protocols.


Jeff Foster.
jfoste@xxxxxxxxxxxx






GSList *HashArray[RootLength];		/* should this be nulled out ??


#define DissectorType void (*dissector)(const u_char *, int, frame_data *, proto_tree *)


typedef struct {
	guint16	Port;
	DissectorType	Dissector;
}DissectorListEntry;


gint DissectorCompare( gpointer D1, pointer D2) {

/* Compare the entry port to the test item port and return 0 if match */

	return !( ((DissectorListEntry*)D1)->Port
		== ((DissectorListEntry*)D1)->Port);
}


gint DissectorDeleteCompare( gpointer D1, pointer D2) {

/* Compare the entry port and dissector to the test item port and dissector */
/* return 0 if match */

	return !( (((DissectorListEntry*)D1)->Port
			== ((DissectorListEntry*)D1)->Port)
		&& (((DissectorListEntry*)D1)->Dissector
			== ((DissectorListEntry*)D1)->Dissector));
}


DissectType *DissectorLookup( DissectorListEntry HashArray[], int HashLength,
	guint16 Port) {

/* find the first entry that has a matching port */

	GSList Entry = HashArray[ Port % HashLength];
	DissectorListEntry Test, *Temp;

	Test.Port = Port;

	if ( !Entry)
		return NULL;

	Temp = (DissectorListEntry*)g_slist_find_custom( EntryList, Test,
		DissectorCompare);

	if ( Temp)
		return Temp->dissector;

	return NULL;
}


void DissectorAdd( GSList *HashArray[], int HashLength, guint16 Port,
	DissectType Dissector) {


/* add an entry,  it is added to the front of the list so if 2 dissectors */
/* for the same port are registered the last one added is used. */

	GSList *Entry = HashArray[ Port % HashLength];

	NewEntry = g_malloc( sizeof( DissectorListEntry));

	NewEntry->Port = Port;
	NewEntry->Dissector = Dissector;

	Entry = g_slist_prepend( Entry, NewEntry);
}


void DissectorDelete( GSList *HashArray[], int HashLength, guint16 Port,
	DissectType Dissector) {

/* delete the entry for this dissector at this port */

	DissectorListEntry Test;
	GSList *EntryList = &HashArray[ Port % HashLength];

	Test.Port = Port
	Test.Dissector = Dissector

	if ( !EntryList)	/* this shouldn't happen, is it needed */
		return;

	Temp = (DissectorListEntry*)g_slist_find_custom( EntryList, Test,
		HashDeleteCompare);

	if ( Temp)
		g_free( Temp->data);
		EntryList = g_slist_remove( Entry, Temp);
	}
}


/******************** TCP Dissector code ******************/

#define TcpDissectorArrayLength;

GSList *TcpDissectorArray[ TcpDissectorArrayLength];


void InitTcpDissect( void) {

	bzero( TcpDissectorArray, sizeof(GSList*) *TcpDissectorArrayLength);

/* Load standard dissectors here */
	
}
	


void TcpDissectorDelete( guint16 Port, DissectType Dissector) {

/* delete dissector from TCP list */

	DissectorDelete( TcpDissectorArray, TcpDissectorArrayLength, Port,
		Dissector);
}


void TcpDissectorAdd( guint16 Port, DissectType Dissector) {

/* add dissector to TCP list */

	DissectorAdd( TcpDissectorArray, TcpDissectorArrayLength, Port,
		Dissector);
}


DissectorType *FindTcpDissector( guint16 Port1, guint16 Port2) {

	DissectorType *Tmp;

	if ( Port1 <= Port2) {
		if ( Tmp = DissectorLookup( TcpDissectorArray,
				TcpDissectorArrayLength, Port1))
			return Tmp;

		return DissectorLookup( TcpDissectorArray,
			TcpDissectorArrayLength, Port2);
	}
	else {
		if ( Tmp = DissectorLookup( TcpDissectorArray,
				TcpDissectorArrayLength, Port2))
			return Tmp;

		return DissectorLookup( TcpDissectorArray,
			TcpDissectorArrayLength, Port1);
	}
}



/******************** UDP Dissector code ******************/


#define UdpDissectorArrayLength XX

GSList *UdpDissectorArray[ UdpDissectorArrayLength];


void InitUDpDissect( void) {

	bzero( UDpDissectorArray, sizeof(GSList*) UdpDissectorArrayLength);

/* Load standard dissectors here */
	
}


void UdpDissectorDelete( guint16 Port, DissectType Dissector) {

/* delete dissector from UDP list */

	DissectorDelete( UdpDissectorArray, UdpDissectorArrayLength, Port,
		Dissector);
}


void UdpDissectorAdd( guint16 Port, DissectType Dissector) {

/* add dissector to UDP list */

	DissectorAdd( UdpDissectorArray, UdpDissectorArrayLength, Port,
		Dissector);
}


DissectorType *FindUdpDissector( guint16 Port1, guint16 Port2) {

/* Find a dissector that matches either port	*/
/* test for lowest numbered port on the assumption it is more likely to match */


	DissectorType *Tmp;

	if ( Port1 <= Port2) {
		if ( Tmp = DissectorLookup( UdpDissectorArray,
				UdpDissectorArrayLength, Port1))
			return Tmp;

		return DissectorLookup( UdpDissectorArray,
				UdpDissectorArrayLength, Port2);
	}
	else {
		if ( Tmp = DissectorLookup( UdpDissectorArray,
				UdpDissectorArrayLength, Port2))
			return Tmp;

		return DissectorLookup( UdpDissectorArray,
				UdpDissectorArrayLength, Port1);
	}
}