From Jeff Morriss: PREF_RANGE preference type, for ranges of integers.
svn path=/trunk/; revision=12300
This commit is contained in:
parent
af061ccd60
commit
abd16b297f
|
@ -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 -
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
41
epan/prefs.c
41
epan/prefs.c
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
60
epan/range.c
60
epan/range.c
|
@ -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)
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue