Ethereal-dev: [Ethereal-dev] [patch] save & load hostname-cache
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Matthijs Melchior <mmelchior@xxxxxxxxx>
Date: Mon, 20 Oct 2003 23:56:33 +0200
Hi, To make it easy on myself when looking at traces from networks without names I have created the following feature. The "Edit>Preferences>Name Resolution" dialog is extended with 2 lines, one to show the file name and one to "Clear", "Load" or "Save" the hostname-cache in a file. This allows you to preload the hostname-cache with names of your choise and not having to remember the IP numbers. And collected IP numbers [with names, if any] can be written to a file for adding hostnames and reloading. There may be a need to connect this to some preferences, but that has not yet been done. Please apply. Thanks. -- Regards, ---------------------------------------------------------------- -o) Matthijs Melchior Maarssen /\\ mmelchior@xxxxxxxxx Netherlands _\_v ---------------------------------------------------------------- ----
diff -u epan/resolv.c-ORG epan/resolv.c --- epan/resolv.c-ORG 2003-08-28 01:01:21.000000000 +0200 +++ epan/resolv.c 2003-10-18 23:14:59.000000000 +0200 @@ -1887,3 +1887,77 @@ return FALSE; } + +/* + * Clear, Save and Load the contants of the hostname-cache. + * Useful for traces from dedicated networks without nameservers: + * clear the name cache, load the trace, save name cache, + * add names to that file, load that file into the cache again. + */ + +void clear_host_cache() +{ + int i; + hashname_t *p, *q; + + for(i=0; i<HASHHOSTSIZE; i++) { + p = host_table[i]; + while(p) { + q = p; + p = p->next; + g_free(q); + } + host_table[i] = NULL; + } +} + +int save_host_cache(char *file) +{ + FILE *hosts; + hashname_t *p; + int i; + char *n; + + hosts = fopen(file, "w"); + if (hosts == 0) { + return -1; + } + fprintf(hosts, "# hostname-cache for ethereal\n\n"); + for(i=0; i<HASHHOSTSIZE; i++) { + p = host_table[i]; + while(p) { + n = p->name; + if (p->is_dummy_entry) + n = "#"; /* create invalid entry ... */ + fprintf(hosts, "%s\t%s\n", ip_to_str((guchar *)&(p->addr)), n); + p = p->next; + } + } + fclose(hosts); + return 0; +} + +int load_host_cache(char *file) +{ + static char sep[] = " \t\r\n"; + FILE *hosts; + int size = 0; + char *buf = NULL; + struct in_addr a; + char *cp; + + hosts = fopen(file, "r"); + if (hosts == 0) { + return -1; + } + while(fgetline(&buf, &size, hosts) >= 0) { + if ((cp = strchr(buf, '#'))) + *cp = '\0'; + if ((cp = strtok(buf, sep))) + if (inet_aton(cp, &a)) + if ((cp = strtok(NULL, sep))) + add_host_name(a.s_addr, cp); + } + + g_free(buf); +} diff -u gtk/nameres_prefs.c-ORG gtk/nameres_prefs.c --- gtk/nameres_prefs.c-ORG 2003-07-22 05:14:31.000000000 +0200 +++ gtk/nameres_prefs.c 2003-10-20 22:49:45.000000000 +0200 @@ -45,17 +45,137 @@ # define C_RESOLVE_KEY "c_resolve" # define RESOLVE_CONCURRENCY_KEY "resolve_concurrency" #endif /* HAVE_GNU_ADNS */ +#define CACHE_FILE_KEY "cache_file_name" +#define E_FS_CALLER_PTR_KEY "fs_caller_ptr" +#define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr" +#define CACHE_FILE_ACTION_FU "cache_file_action_fu" #ifdef HAVE_GNU_ADNS -# define RESOLV_TABLE_ROWS 5 +# define RESOLV_TABLE_ROWS 7 #else -# define RESOLV_TABLE_ROWS 3 +# define RESOLV_TABLE_ROWS 5 #endif /* HAVE_GNU_ADNS */ + +void dlg_set_cancel(GtkWidget *widget, GtkWidget *cancel_button); +char* get_persconffile_path(const char *filename, gboolean for_writing); + +typedef int (*actionfu)(gchar *file); /* for function pointers as parameter */ + +int load_host_cache(gchar *file); +int save_host_cache(gchar *file); +int clear_host_cache(); + +/* This could be a preference */ +static gchar *hosts_cache_filename = 0; + +static void +cache_fs_cancel_cb(GtkWidget *w _U_, gpointer data) +{ + gtk_widget_destroy(GTK_WIDGET(data)); +} + +static void +cache_fs_ok_cb(GtkWidget *w, gpointer data) +{ + gchar * name = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(data)); + actionfu action = OBJECT_GET_DATA(data, CACHE_FILE_ACTION_FU); + + gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, CACHE_FILE_KEY)), name); + cache_fs_cancel_cb(w, data); + + action(name); /* do it */ +} + +static void +cache_fs_destroy_cb(GtkWidget *win, gpointer data _U_) +{ + GtkWidget *caller; + + /* Get the widget that requested that we be popped up. + (It should arrange to destroy us if it's destroyed, so + that we don't get a pointer to a non-existent window here.) */ + caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY); + + /* Tell it we no longer exist. */ + OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL); + + /* Now nuke this window. */ + gtk_grab_remove(GTK_WIDGET(win)); + gtk_widget_destroy(GTK_WIDGET(win)); +} + + +static void +handle_hostname_cache(GtkWidget *w, gpointer data, actionfu action, gchar *title) +{ + GtkWidget *caller = gtk_widget_get_toplevel(w); + GtkWidget *fs; + + /* Has a file selection dialog box already been opened for that top-level + widget? */ + fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY); + + if (fs != NULL) { + /* Yes. Just re-activate that dialog box. */ + reactivate_window(fs); + return; + } + + fs = gtk_file_selection_new (title); + OBJECT_SET_DATA(fs, CACHE_FILE_KEY, data); + OBJECT_SET_DATA(fs, CACHE_FILE_ACTION_FU, action); + + /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */ + OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller); + + /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */ + OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs); + + gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), gtk_entry_get_text(GTK_ENTRY(data))); + + /* Call a handler when the file selection box is destroyed, so we can inform + our caller, if any, that it's been destroyed. */ + SIGNAL_CONNECT(fs, "destroy", cache_fs_destroy_cb, NULL); + + SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked", + cache_fs_ok_cb, fs); + + /* Connect the cancel_button to destroy the widget */ + SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked", + cache_fs_cancel_cb, fs); + + /* Catch the "key_press_event" signal in the window, so that we can catch + the ESC key being pressed and act as if the "Cancel" button had + been selected. */ + dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button); + + gtk_widget_show(fs); +} + +static void +load_cache_cb(GtkWidget *w, gpointer data) +{ + handle_hostname_cache(w, data, load_host_cache, "Ethereal: Load hostname cache from File"); +} +static void +save_cache_cb(GtkWidget *w, gpointer data) +{ + handle_hostname_cache(w, data, save_host_cache, "Ethereal: Save hostname cache in File"); +} + +static void +clear_cache_cb(GtkWidget *w _U_, gpointer data _U_) +{ + clear_host_cache(); +} + GtkWidget* nameres_prefs_show(void) { GtkWidget *main_tb, *main_vb; GtkWidget *m_resolv_cb, *n_resolv_cb, *t_resolv_cb; + GtkWidget *cache_hb, *clear_bt, *save_bt, *load_bt, *file_te; + GtkWidget *label, *event_box; #ifdef HAVE_GNU_ADNS GtkWidget *c_resolv_cb, *resolv_concurrency_te; char concur_str[10+1]; @@ -115,6 +235,66 @@ #endif /* HAVE_GNU_ADNS */ + label = gtk_label_new("Ethereal hostname-cache filename:"); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + gtk_widget_show(label); + + event_box = gtk_event_box_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1, 5, 6); + gtk_container_add(GTK_CONTAINER(event_box), label); + gtk_widget_show(event_box); + + label = gtk_label_new("Ethereal hostname-cache operations:"); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + gtk_widget_show(label); + + event_box = gtk_event_box_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1, 6, 7); + gtk_container_add(GTK_CONTAINER(event_box), label); + gtk_widget_show(event_box); + + file_te = gtk_entry_new(); + OBJECT_SET_DATA(main_tb, CACHE_FILE_KEY, file_te); + if (hosts_cache_filename == 0) /* this could be a preference */ + hosts_cache_filename = get_persconffile_path("hostname-cache", TRUE); + gtk_entry_set_text(GTK_ENTRY(file_te), hosts_cache_filename); + gtk_table_attach_defaults(GTK_TABLE(main_tb), file_te, 1, 2, 5, 6); + gtk_widget_show(file_te); + + cache_hb = gtk_hbox_new(TRUE, 8); + gtk_table_attach_defaults(GTK_TABLE(main_tb), cache_hb, 1, 2, 6, 7); + gtk_widget_show(cache_hb); + +#if GTK_MAJOR_VERSION < 2 + clear_bt = gtk_button_new_with_label("Clear"); +#else + clear_bt = gtk_button_new_from_stock(GTK_STOCK_CLEAR); +#endif + gtk_widget_set_sensitive(clear_bt, TRUE); + SIGNAL_CONNECT(clear_bt, "clicked", clear_cache_cb, NULL); + gtk_box_pack_start(GTK_BOX(cache_hb), clear_bt, TRUE, TRUE, 0); + gtk_widget_show(clear_bt); + +#if GTK_MAJOR_VERSION < 2 + load_bt = gtk_button_new_with_label("Load"); +#else + load_bt = gtk_button_new_from_stock(GTK_STOCK_OPEN); /* don't have GTK_STOCK_LOAD ... ? */ +#endif + gtk_widget_set_sensitive(load_bt, TRUE); + SIGNAL_CONNECT(load_bt, "clicked", load_cache_cb, file_te); + gtk_box_pack_start(GTK_BOX(cache_hb), load_bt, TRUE, TRUE, 0); + gtk_widget_show(load_bt); + +#if GTK_MAJOR_VERSION < 2 + save_bt = gtk_button_new_with_label("Save"); +#else + save_bt = gtk_button_new_from_stock(GTK_STOCK_SAVE); +#endif + gtk_widget_set_sensitive(save_bt, TRUE); + SIGNAL_CONNECT(save_bt, "clicked", save_cache_cb, file_te); + gtk_box_pack_start(GTK_BOX(cache_hb), save_bt, TRUE, TRUE, 0); + gtk_widget_show(save_bt); + /* Show 'em what we got */ gtk_widget_show_all(main_vb);
- Follow-Ups:
- Re: [Ethereal-dev] [patch] save & load hostname-cache
- From: Ronnie Sahlberg
- Re: [Ethereal-dev] [patch] save & load hostname-cache
- From: Guy Harris
- Re: [Ethereal-dev] [patch] save & load hostname-cache
- Prev by Date: Re: [Ethereal-dev] Time for the next release?
- Next by Date: Re: [Ethereal-dev] Time for the next release?
- Previous by thread: Re: [Ethereal-dev] Discussion of A Common Representation of Protocols
- Next by thread: Re: [Ethereal-dev] [patch] save & load hostname-cache
- Index(es):