Use a hastable for port resolution. Currently one table for the 4 protocols with resolution. SCTP and DCCP should perhaps be splited out to their own tables.

svn path=/trunk/; revision=51153
This commit is contained in:
Anders Broman 2013-08-05 16:36:24 +00:00
parent 86472b67df
commit 21d5a76a68
3 changed files with 177 additions and 119 deletions

View File

@ -233,12 +233,15 @@ typedef struct {
#define HASH_PORT(port) ((port) & (HASHPORTSIZE - 1))
typedef struct hashport {
guint16 port;
struct hashport *next;
gchar name[MAXNAMELEN];
} hashport_t;
#if 0
typedef struct serv_port {
gchar *udp_name;
gchar *tcp_name;
gchar *sctp_name;
gchar *dccp_name;
} serv_port_t;
#endif
/* hash table used for IPX network lookup */
/* XXX - check goodness of hash function */
@ -252,11 +255,6 @@ typedef struct hashipxnet {
} hashipxnet_t;
/* hash tables used for ethernet and manufacturer lookup */
#define HASH_ETH_ADDRESS(addr) \
(((((addr)[2] << 8) | (addr)[3]) ^ (((addr)[4] << 8) | (addr)[5])) & \
(HASHETHSIZE - 1))
#define HASHETHER_STATUS_UNRESOLVED 1
#define HASHETHER_STATUS_RESOLVED_DUMMY 2
#define HASHETHER_STATUS_RESOLVED_NAME 3
@ -289,17 +287,15 @@ typedef struct _ipxnet
static hashipv4_t *ipv4_table[HASHHOSTSIZE];
static hashipv6_t *ipv6_table[HASHHOSTSIZE];
static hashport_t **cb_port_table;
static gchar *cb_service;
static port_type cb_proto = PT_NONE;
static GHashTable *manuf_hashtable = NULL;
static GHashTable *wka_hashtable = NULL;
static GHashTable *eth_hashtable = NULL;
static GHashTable *serv_port_hashtable = NULL;
static hashport_t *udp_port_table[HASHPORTSIZE];
static hashport_t *tcp_port_table[HASHPORTSIZE];
static hashport_t *sctp_port_table[HASHPORTSIZE];
static hashport_t *dccp_port_table[HASHPORTSIZE];
static hashipxnet_t *ipxnet_table[HASHIPXNETSIZE];
static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE]; /* Ordered array of entries */
@ -480,36 +476,43 @@ static void subnet_entry_set(guint32 subnet_addr, const guint32 mask_length, con
static void
add_service_name(hashport_t **proto_table, const guint port, const char *service_name)
add_service_name(port_type proto, const guint port, const char *service_name)
{
int hash_idx;
hashport_t *tp;
serv_port_t *serv_port_table;
int *key;
key = (int *)g_new(int, 1);
*key = port;
hash_idx = HASH_PORT(port);
tp = proto_table[hash_idx];
if( tp == NULL ) {
tp = proto_table[hash_idx] = se_new(hashport_t);
if (serv_port_hashtable == NULL){
serv_port_hashtable = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
serv_port_table = g_new0(serv_port_t,1);
g_hash_table_insert(serv_port_hashtable, key, serv_port_table);
} else {
while(1) {
if( tp->port == port ) {
return;
}
if (tp->next == NULL) {
tp->next = se_new(hashport_t);
tp = tp->next;
break;
}
tp = tp->next;
}
serv_port_table = (serv_port_t *)g_hash_table_lookup(serv_port_hashtable, &port);
if(serv_port_table == NULL){
serv_port_table = g_new0(serv_port_t,1);
g_hash_table_insert(serv_port_hashtable, key, serv_port_table);
}
}
/* fill in a new entry */
tp->port = port;
tp->next = NULL;
g_strlcpy(tp->name, service_name, MAXNAMELEN);
switch(proto){
case PT_TCP:
serv_port_table->tcp_name = g_strdup(service_name);
break;
case PT_UDP:
serv_port_table->udp_name = g_strdup(service_name);
break;
case PT_SCTP:
serv_port_table->sctp_name = g_strdup(service_name);
break;
case PT_DCCP:
serv_port_table->dccp_name = g_strdup(service_name);
break;
default:
return;
/* Should not happen */
}
new_resolved_objects = TRUE;
}
@ -526,6 +529,7 @@ parse_service_line (char *line)
gchar *cp;
gchar *service;
gchar *port;
port_type proto;
range_t *port_rng = NULL;
guint32 max_port = MAX_UDP_PORT;
@ -552,19 +556,19 @@ parse_service_line (char *line)
/* seems we got all interesting things from the file */
if(strcmp(cp, "tcp") == 0) {
max_port = MAX_TCP_PORT;
cb_port_table = tcp_port_table;
proto = PT_TCP;
}
else if(strcmp(cp, "udp") == 0) {
max_port = MAX_UDP_PORT;
cb_port_table = udp_port_table;
proto = PT_UDP;
}
else if(strcmp(cp, "sctp") == 0) {
max_port = MAX_SCTP_PORT;
cb_port_table = sctp_port_table;
proto = PT_SCTP;
}
else if(strcmp(cp, "dccp") == 0) {
max_port = MAX_DCCP_PORT;
cb_port_table = dccp_port_table;
proto = PT_DCCP;
} else {
return;
}
@ -575,8 +579,10 @@ parse_service_line (char *line)
}
cb_service = service;
cb_proto = proto;
range_foreach(port_rng, add_serv_port_cb);
g_free (port_rng);
cb_proto = PT_NONE;
} /* parse_service_line */
@ -584,7 +590,7 @@ static void
add_serv_port_cb(const guint32 port)
{
if ( port ) {
add_service_name(cb_port_table, port, cb_service);
add_service_name(cb_proto, port, cb_service);
}
}
@ -631,84 +637,102 @@ initialize_services(void)
} /* initialize_services */
/* -----------------
* unsigned integer to ascii
*/
static gchar *
ep_utoa(guint port)
{
gchar *bp = (gchar *)ep_alloc(MAXNAMELEN);
/* XXX, guint32_to_str() ? */
guint32_to_str_buf(port, bp, MAXNAMELEN);
return bp;
}
static gchar
*serv_name_lookup(const guint port, const port_type proto)
{
int hash_idx;
hashport_t *tp;
hashport_t **table;
const char *serv_proto = NULL;
struct servent *servp;
serv_port_t *serv_port_table;
if (!service_resolution_initialized) {
initialize_services();
}
/* Set which table we should look up port in */
switch(proto) {
case PT_UDP:
table = udp_port_table;
serv_proto = "udp";
break;
case PT_TCP:
table = tcp_port_table;
serv_proto = "tcp";
break;
case PT_SCTP:
table = sctp_port_table;
serv_proto = "sctp";
break;
case PT_DCCP:
table = dccp_port_table;
serv_proto = "dcp";
break;
default:
/* not yet implemented */
return NULL;
/*NOTREACHED*/
} /* proto */
/* Look for port in table */
hash_idx = HASH_PORT(port);
tp = table[hash_idx];
if( tp == NULL ) {
/* Not found so allocate new entry */
tp = table[hash_idx] = se_new(hashport_t);
} else {
/* Hash matched, but need to loop around entries looking for matching port */
while(1) {
if( tp->port == port ) {
/* Found matching entry, return name! */
return tp->name;
}
if (tp->next == NULL) {
/* Reached end of current list without match. Allocate and add to end of list */
tp->next = se_new(hashport_t);
tp = tp->next;
break;
}
/* Try next entry */
tp = tp->next;
}
if((proto != PT_UDP)||(proto != PT_TCP)||(proto != PT_SCTP)||(proto != PT_DCCP)){
return NULL; /* not yet implemented */
}
/* Fill in a new entry (which must be at the end of its list) */
tp->port = port;
tp->next = NULL;
serv_port_table = (serv_port_t *)g_hash_table_lookup(serv_port_hashtable, &port);
if(serv_port_table){
/* Set which table we should look up port in */
switch(proto) {
case PT_UDP:
if(serv_port_table->udp_name){
return serv_port_table->udp_name;
}
serv_proto = "udp";
break;
case PT_TCP:
if(serv_port_table->tcp_name){
return serv_port_table->tcp_name;
}
serv_proto = "tcp";
break;
case PT_SCTP:
if(serv_port_table->sctp_name){
return serv_port_table->sctp_name;
}
serv_proto = "sctp";
break;
case PT_DCCP:
if(serv_port_table->dccp_name){
return serv_port_table->dccp_name;
}
serv_proto = "dcp";
break;
default:
/* not yet implemented */
return NULL;
/*NOTREACHED*/
} /* proto */
}
if ((!gbl_resolv_flags.transport_name) ||
(servp = getservbyport(g_htons(port), serv_proto)) == NULL) {
/* unknown port */
guint32_to_str_buf(port, tp->name, MAXNAMELEN);
return ep_utoa(port);
} else {
g_strlcpy(tp->name, servp->s_name, MAXNAMELEN);
if(serv_port_table == NULL){
int *key;
key = (int *)g_new(int, 1);
*key = port;
serv_port_table = g_new0(serv_port_t,1);
g_hash_table_insert(serv_port_hashtable, key, serv_port_table);
}
switch(proto) {
case PT_UDP:
serv_port_table->udp_name = servp->s_name;
break;
case PT_TCP:
serv_port_table->tcp_name = servp->s_name;
break;
case PT_SCTP:
serv_port_table->sctp_name = servp->s_name;
break;
case PT_DCCP:
serv_port_table->dccp_name = servp->s_name;
break;
}
return servp->s_name;
}
return (tp->name);
} /* serv_name_lookup */
@ -2700,10 +2724,6 @@ host_name_lookup_cleanup(void) {
memset(ipv4_table, 0, sizeof(ipv4_table));
memset(ipv6_table, 0, sizeof(ipv6_table));
memset(udp_port_table, 0, sizeof(udp_port_table));
memset(tcp_port_table, 0, sizeof(tcp_port_table));
memset(sctp_port_table, 0, sizeof(sctp_port_table));
memset(dccp_port_table, 0, sizeof(dccp_port_table));
memset(ipxnet_table, 0, sizeof(ipxnet_table));
memset(subnet_length_entries, 0, sizeof(subnet_length_entries));
@ -2711,7 +2731,6 @@ host_name_lookup_cleanup(void) {
have_subnet_entry = FALSE;
ipxnet_resolution_initialized = FALSE;
service_resolution_initialized = FALSE;
new_resolved_objects = FALSE;
}
@ -2733,7 +2752,13 @@ eth_name_lookup_cleanup(void) {
eth_hashtable = NULL;
}
if(serv_port_hashtable){
g_hash_table_destroy(serv_port_hashtable);
eth_hashtable = NULL;
}
eth_resolution_initialized = FALSE;
service_resolution_initialized = FALSE;
}
const gchar *
@ -2900,20 +2925,6 @@ add_ipv6_name(const struct e_in6_addr *addrp, const gchar *name)
} /* add_ipv6_name */
/* -----------------
* unsigned integer to ascii
*/
static gchar *
ep_utoa(guint port)
{
gchar *bp = (gchar *)ep_alloc(MAXNAMELEN);
/* XXX, guint32_to_str() ? */
guint32_to_str_buf(port, bp, MAXNAMELEN);
return bp;
}
gchar *
get_udp_port(guint port)
{
@ -3486,3 +3497,9 @@ get_eth_hashtable(void)
return eth_hashtable;
}
GHashTable *
get_serv_port_hashtable(void)
{
return serv_port_hashtable;
}

View File

@ -63,6 +63,13 @@ typedef struct hashether {
char resolved_name[MAXNAMELEN];
} hashether_t;
typedef struct serv_port {
gchar *udp_name;
gchar *tcp_name;
gchar *sctp_name;
gchar *dccp_name;
} serv_port_t;
/*
* Flag controlling what names to resolve.
*/
@ -314,6 +321,9 @@ GHashTable *get_wka_hashtable(void);
WS_DLL_PUBLIC
GHashTable *get_eth_hashtable(void);
WS_DLL_PUBLIC
GHashTable *get_serv_port_hashtable(void);
WS_DLL_PUBLIC
void initialize_ethers(void);

View File

@ -216,6 +216,25 @@ wka_hash_to_texbuff(gpointer key, gpointer value, gpointer user_data)
}
static void
serv_port_hash_to_texbuff(gpointer key, gpointer value, gpointer user_data)
{
gchar string_buff[ADDRESS_STR_MAX];
GtkTextBuffer *buffer = (GtkTextBuffer*)user_data;
serv_port_t *serv_port_table = (serv_port_t *)value;
int port = *(int*)key;
g_snprintf(string_buff, ADDRESS_STR_MAX, "Port %u \n"" TCP %s\n"" UDP %s\n"" SCTP %s\n"" DCCP %s\n",
port,
serv_port_table->tcp_name,
serv_port_table->udp_name,
serv_port_table->sctp_name,
serv_port_table->dccp_name);
gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);
}
static void
addres_resolution_to_texbuff(GtkTextBuffer *buffer)
{
@ -228,6 +247,7 @@ addres_resolution_to_texbuff(GtkTextBuffer *buffer)
GHashTable *manuf_hashtable;
GHashTable *wka_hashtable;
GHashTable *eth_hashtable;
GHashTable *serv_port_hashtable;
g_snprintf(string_buff, ADDRESS_STR_MAX, "# Hosts information in Wireshark \n#\n");
gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);
@ -274,6 +294,17 @@ addres_resolution_to_texbuff(GtkTextBuffer *buffer)
}
}
g_snprintf(string_buff, ADDRESS_STR_MAX, "\n\n# Port names information in Wireshark \n#\n");
gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);
serv_port_hashtable = get_serv_port_hashtable();
if(serv_port_hashtable){
g_snprintf(string_buff, ADDRESS_STR_MAX, "# With %i entries\n#\n", g_hash_table_size(serv_port_hashtable));
gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);
g_hash_table_foreach( serv_port_hashtable, serv_port_hash_to_texbuff, buffer);
}
g_snprintf(string_buff, ADDRESS_STR_MAX, "\n\n# Eth names information in Wireshark \n#\n");
gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);