From Jeff Morriss: PREF_RANGE preference type, for ranges of integers.

svn path=/trunk/; revision=12300
This commit is contained in:
Guy Harris 2004-10-14 23:45:09 +00:00
parent af061ccd60
commit abd16b297f
8 changed files with 237 additions and 22 deletions

View File

@ -2442,6 +2442,13 @@ Then you can register the fields that can be configured by the user with these r
void prefs_register_string_preference(module_t *module, const char *name,
const char *title, const char *description, char **var)
/* Register a preference with a range of unsigned integers (e.g.,
* "1-20,30-40").
*/
void prefs_register_range_preference(module_t *module, const char *name,
const char *title, const char *description, range_t *var,
guint32 max_value)
Where: module - Returned by the prefs_register_protocol routine
name - This is appended to the name of the protocol, with a
"." between them, to construct a name that identifies
@ -2472,6 +2479,7 @@ Where: module - Returned by the prefs_register_protocol routine
preferences dialog as a set of radio buttons,
FALSE if it is to be displayed as an option
menu
max_value - The maximum allowed value for a range (0 is the minimum).
An example from packet-beep.c -

View File

@ -66,6 +66,10 @@
Tcap_Standard_Type tcap_standard = ITU_TCAP_STANDARD;
#define MAX_SSN 254
static range_t global_ssn_range;
static range_t ssn_range;
/* saved pinfo */
static packet_info *g_pinfo = NULL;
static proto_tree *g_tcap_tree = NULL;
@ -2741,6 +2745,8 @@ dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* Register the protocol with Ethereal */
void proto_reg_handoff_tcap(void);
/* this format is require because a script is used to build the C function
that calls all the protocol registration.
*/
@ -2846,7 +2852,7 @@ proto_register_tcap(void)
proto_register_field_array(proto_tcap, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
tcap_module = prefs_register_protocol(proto_tcap, NULL);
tcap_module = prefs_register_protocol(proto_tcap, proto_reg_handoff_tcap);
prefs_register_enum_preference(tcap_module, "standard", "TCAP standard",
"The SS7 standard used in TCAP packets",
@ -2856,6 +2862,14 @@ proto_register_tcap(void)
"Always show TCAP in Info column",
&lock_info_col);
/* Set default SSNs */
range_convert_str(&global_ssn_range, "5-12", MAX_SSN);
memset(&ssn_range, 0, sizeof(ssn_range));
prefs_register_range_preference(tcap_module, "ssn", "SCCP SSNs",
"SCCP (and SUA) SSNs to decode as TCAP",
&global_ssn_range, MAX_SSN);
/* we will fake a ssn subfield which has the same value obtained from sccp */
tcap_itu_ssn_dissector_table = register_dissector_table("tcap.itu_ssn", "ITU TCAP SSN", FT_UINT8, BASE_DEC);
tcap_ansi_ssn_dissector_table = register_dissector_table("tcap.ansi_ssn", "ANSI TCAP SSN", FT_UINT8, BASE_DEC);
@ -2869,28 +2883,38 @@ proto_register_tcap(void)
void
proto_reg_handoff_tcap(void)
{
dissector_handle_t tcap_handle;
static dissector_handle_t tcap_handle;
static gboolean prefs_initialized = FALSE;
tcap_handle = create_dissector_handle(dissect_tcap,
proto_tcap);
static void range_delete_callback(guint32 ssn)
{
if (ssn) {
dissector_delete("sccp.ssn", ssn, tcap_handle);
dissector_delete("sua.ssn", ssn, tcap_handle);
}
}
static void range_add_callback(guint32 ssn)
{
if (ssn) {
dissector_add("sccp.ssn", ssn, tcap_handle);
dissector_add("sua.ssn", ssn, tcap_handle);
}
}
dissector_add("sccp.ssn", 5, tcap_handle); /* MAP*/
dissector_add("sccp.ssn", 6, tcap_handle); /* HLR*/
dissector_add("sccp.ssn", 7, tcap_handle); /* VLR */
dissector_add("sccp.ssn", 8, tcap_handle); /* MSC */
dissector_add("sccp.ssn", 9, tcap_handle); /* EIR */
dissector_add("sccp.ssn", 10, tcap_handle); /* EIR */
dissector_add("sccp.ssn", 11, tcap_handle); /* SMS/MC */
dissector_add("sccp.ssn", 12, tcap_handle); /* IS41 OTAF */
if (!prefs_initialized) {
dissector_add("sua.ssn", 5, tcap_handle); /* MAP*/
dissector_add("sua.ssn", 6, tcap_handle); /* HLR*/
dissector_add("sua.ssn", 7, tcap_handle); /* VLR */
dissector_add("sua.ssn", 8, tcap_handle); /* MSC */
dissector_add("sua.ssn", 9, tcap_handle); /* EIR */
dissector_add("sua.ssn", 10, tcap_handle); /* EIR */
dissector_add("sua.ssn", 11, tcap_handle); /* SMS/MC */
dissector_add("sua.ssn", 12, tcap_handle); /* IS41 OTAF */
tcap_handle = create_dissector_handle(dissect_tcap, proto_tcap);
data_handle = find_dissector("data");
prefs_initialized = TRUE;
} else {
range_foreach(&ssn_range, range_delete_callback);
}
ssn_range = global_ssn_range;
range_foreach(&ssn_range, range_add_callback);
data_handle = find_dissector("data");
}

View File

@ -53,6 +53,7 @@ typedef enum {
PREF_BOOL,
PREF_ENUM,
PREF_STRING,
PREF_RANGE,
PREF_OBSOLETE
} pref_type_t;
@ -67,15 +68,18 @@ struct preference {
gboolean *boolp;
gint *enump;
char **string;
range_t *rangep;
} varp; /* pointer to variable storing the value */
union {
guint uint;
gboolean boolval;
gint enumval;
char *string;
range_t rangeval;
} saved_val; /* original value, when editing from the GUI */
union {
guint base; /* input/output base, for PREF_UINT */
guint32 max_value; /* maximum value of a range */
struct {
const enum_val_t *enumvals; /* list of name & values */
gboolean radio_buttons; /* TRUE if it should be shown as

View File

@ -579,6 +579,24 @@ prefs_register_string_preference(module_t *module, const char *name,
preference->saved_val.string = NULL;
}
/*
* Register a preference with a ranged value.
*/
void
prefs_register_range_preference(module_t *module, const char *name,
const char *title, const char *description, range_t *var,
guint32 max_value)
{
pref_t *preference;
preference = register_preference(module, name, title, description,
PREF_RANGE);
preference->info.max_value = max_value;
preference->varp.rangep = var;
memset(&preference->saved_val.rangeval, 0, sizeof(preference->saved_val.rangeval));
}
/*
* Register a preference that used to be supported but no longer is.
*/
@ -1992,6 +2010,19 @@ set_pref(gchar *pref_name, gchar *value)
}
break;
case PREF_RANGE:
{
range_t newrange;
range_convert_str(&newrange, value, pref->info.max_value);
if (!ranges_are_equal(pref->varp.rangep, &newrange)) {
module->prefs_changed = TRUE;
*pref->varp.rangep = newrange;
}
break;
}
case PREF_OBSOLETE:
return PREFS_SET_OBSOLETE; /* no such preference any more */
}
@ -2091,6 +2122,16 @@ write_pref(gpointer data, gpointer user_data)
*pref->varp.string);
break;
case PREF_RANGE:
{
char range_string[MAXRANGESTRING];
fprintf(arg->pf, "# A string denoting an positive integer range (e.g., \"1-20,30-40\").\n");
fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
range_convert_range(pref->varp.rangep, range_string));
break;
}
case PREF_OBSOLETE:
g_assert_not_reached();
break;

View File

@ -29,6 +29,8 @@
#include "color.h"
#include <epan/range.h>
#define PR_DEST_CMD 0
#define PR_DEST_FILE 1
@ -274,6 +276,13 @@ extern void prefs_register_enum_preference(module_t *module, const char *name,
extern void prefs_register_string_preference(module_t *module, const char *name,
const char *title, const char *description, char **var);
/*
* Register a preference with a ranged value.
*/
extern void prefs_register_range_preference(module_t *module, const char *name,
const char *title, const char *description, range_t *var,
guint32 max_value);
/*
* Register a preference that used to be supported but no longer is.
*/

View File

@ -37,6 +37,7 @@
#include <epan/frame_data.h>
#include <epan/range.h>
#include <stdio.h>
/* init the range struct */
void range_init(range_t *range) {
@ -73,7 +74,8 @@ void range_init(range_t *range) {
void range_convert_str(range_t *range, const gchar *es, guint32 max_value)
{
gchar EntryStr[255], OrgStr[255], value[255], p;
gchar EntryStr[MAXRANGESTRING], OrgStr[MAXRANGESTRING];
gchar value[MAXRANGESTRING], p;
guint i, j=0;
guint32 tmp, val;
gboolean hyphenseen;
@ -241,6 +243,62 @@ gboolean value_is_in_range(range_t *range, guint32 val)
return(FALSE);
}
/* This function returns TRUE if the two given range_t's are equal.
*/
gboolean ranges_are_equal(range_t *a, range_t *b)
{
guint i;
if (a->nranges != b->nranges)
return FALSE;
for (i=0; i <= a->nranges; i++) {
if (a->ranges[i].low != b->ranges[i].low)
return FALSE;
if (a->ranges[i].high != b->ranges[i].high)
return FALSE;
}
return TRUE;
}
/* This function calls the provided callback function for each value in
* in the range.
*/
void
range_foreach(range_t *range, void (*callback)(guint32 val))
{
guint32 i, j;
for (i=0; i <= range->nranges; i++) {
for (j = range->ranges[i].low; j <= range->ranges[i].high; j++)
callback(j);
}
}
/* This function converts a range_t to a (caller-provided) string. */
char *
range_convert_range(range_t *range, char *string)
{
guint32 i, k;
k = 0;
string[k] = '\0';
for (i=0; i <= range->nranges; i++) {
if (i != 0)
string[k++] = ',';
k += sprintf(&string[k], "%d-%d", range->ranges[i].low,
range->ranges[i].high);
}
return(string);
}
#if 0
/* This is a debug function to check the range functionality */
static void value_is_in_range_check(range_t *range, guint32 val)

View File

@ -35,6 +35,8 @@
/* Range parser variables */
#define MaxRange 30
#define MAXRANGESTRING 255
typedef struct range_admin_tag {
guint32 low;
guint32 high;
@ -53,4 +55,10 @@ extern void range_convert_str(range_t *range, const gchar *es,
extern gboolean value_is_in_range(range_t *range, guint32 val);
extern gboolean ranges_are_equal(range_t *a, range_t *b);
extern void range_foreach(range_t *range, void (*callback)(guint32 val));
extern char *range_convert_range(range_t *range, char *string);
#endif /* __RANGE_H__ */

View File

@ -202,6 +202,18 @@ pref_show(pref_t *pref, gpointer user_data)
pref->saved_val.string);
break;
case PREF_RANGE:
{
char range_string[MAXRANGESTRING];
pref->saved_val.rangeval = *pref->varp.rangep;
range_convert_range(pref->varp.rangep, range_string);
pref->control = create_preference_entry(main_tb, pref->ordinal,
label_string, pref->description,
range_string);
break;
}
case PREF_OBSOLETE:
g_assert_not_reached();
break;
@ -886,6 +898,24 @@ pref_check(pref_t *pref, gpointer user_data)
/* Value can't be bad. */
break;
case PREF_RANGE:
str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
if (strlen(str_val)) {
range_t newrange;
range_convert_str(&newrange, str_val, pref->info.max_value);
if (newrange.nranges == 0) {
/* If the user specified a string of non-zero length but
* range_convert_str() couldn't find a single range in it,
* it must be bad.
*/
*badpref = pref;
return PREFS_SET_SYNTAX_ERR; /* range was bad */
}
}
break;
case PREF_OBSOLETE:
g_assert_not_reached();
break;
@ -960,6 +990,22 @@ pref_fetch(pref_t *pref, gpointer user_data)
}
break;
case PREF_RANGE:
{
range_t newrange;
str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
range_convert_str(&newrange, str_val, pref->info.max_value);
if (!ranges_are_equal(pref->varp.rangep, &newrange))
{
*pref_changed_p = TRUE;
*pref->varp.rangep = newrange;
}
break;
}
case PREF_OBSOLETE:
g_assert_not_reached();
break;
@ -1007,6 +1053,9 @@ pref_clean(pref_t *pref, gpointer user_data _U_)
}
break;
case PREF_RANGE:
break;
case PREF_OBSOLETE:
g_assert_not_reached();
break;
@ -1042,6 +1091,12 @@ prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
badpref->title);
return FALSE;
case PREF_RANGE:
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"The value for \"%s\" is not a valid range.",
badpref->title);
return FALSE;
default:
g_assert_not_reached();
break;
@ -1257,6 +1312,14 @@ pref_revert(pref_t *pref, gpointer user_data)
}
break;
case PREF_RANGE:
if (!ranges_are_equal(pref->varp.rangep, &pref->saved_val.rangeval))
{
*pref_changed_p = TRUE;
*pref->varp.rangep = pref->saved_val.rangeval;
}
break;
case PREF_OBSOLETE:
g_assert_not_reached();
break;