2007-01-28 10:31:32 +00:00
|
|
|
/*
|
|
|
|
* uat.c
|
|
|
|
*
|
|
|
|
* User Accessible Tables
|
2015-11-15 20:06:10 +00:00
|
|
|
* Maintain an array of user accessible data structures
|
2007-01-28 10:31:32 +00:00
|
|
|
*
|
2008-08-05 21:03:46 +00:00
|
|
|
* (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
|
2007-01-29 04:47:58 +00:00
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 2001 Gerald Combs
|
2007-10-16 15:43:18 +00:00
|
|
|
*
|
2018-02-08 16:59:17 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2007-01-28 10:31:32 +00:00
|
|
|
*/
|
2012-09-20 01:48:30 +00:00
|
|
|
#include "config.h"
|
2007-01-28 10:31:32 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include <glib.h>
|
2008-09-03 19:14:52 +00:00
|
|
|
|
|
|
|
#include <wsutil/file_util.h>
|
|
|
|
#include <wsutil/str_util.h>
|
2017-04-08 19:45:19 +00:00
|
|
|
#include <wsutil/report_message.h>
|
2021-06-18 18:21:42 +00:00
|
|
|
#include <wsutil/ws_assert.h>
|
2008-09-03 19:14:52 +00:00
|
|
|
|
2013-11-17 02:55:14 +00:00
|
|
|
#include <wsutil/filesystem.h>
|
2007-02-03 14:25:02 +00:00
|
|
|
#include <epan/packet.h>
|
2007-04-03 19:08:00 +00:00
|
|
|
#include <epan/range.h>
|
2007-01-28 10:31:32 +00:00
|
|
|
|
|
|
|
#include "uat-int.h"
|
|
|
|
|
2016-08-14 20:49:19 +00:00
|
|
|
/*
|
|
|
|
* XXX Files are encoded as ASCII. We might want to encode them as UTF8
|
|
|
|
* instead.
|
|
|
|
*/
|
|
|
|
|
2007-01-28 10:31:32 +00:00
|
|
|
static GPtrArray* all_uats = NULL;
|
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
uat_t* uat_new(const char* name,
|
2011-09-21 18:55:03 +00:00
|
|
|
size_t size,
|
|
|
|
const char* filename,
|
|
|
|
gboolean from_profile,
|
2014-01-30 17:43:52 +00:00
|
|
|
void* data_ptr,
|
2011-09-21 18:55:03 +00:00
|
|
|
guint* numitems_ptr,
|
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
|
|
|
guint flags,
|
2011-09-21 18:55:03 +00:00
|
|
|
const char* help,
|
|
|
|
uat_copy_cb_t copy_cb,
|
|
|
|
uat_update_cb_t update_cb,
|
|
|
|
uat_free_cb_t free_cb,
|
|
|
|
uat_post_update_cb_t post_update_cb,
|
2016-12-21 10:50:47 +00:00
|
|
|
uat_reset_cb_t reset_cb,
|
2011-09-21 18:55:03 +00:00
|
|
|
uat_field_t* flds_array) {
|
|
|
|
/* Create new uat */
|
2020-12-21 02:30:28 +00:00
|
|
|
uat_t* uat = g_new(uat_t, 1);
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
|
|
|
|
|
|
|
/* Add to global array of uats */
|
|
|
|
if (!all_uats)
|
|
|
|
all_uats = g_ptr_array_new();
|
|
|
|
|
|
|
|
g_ptr_array_add(all_uats,uat);
|
|
|
|
|
|
|
|
/* Check params */
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert(name && size && filename && data_ptr && numitems_ptr);
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
/* Set uat values from inputs */
|
|
|
|
uat->name = g_strdup(name);
|
|
|
|
uat->record_size = size;
|
|
|
|
uat->filename = g_strdup(filename);
|
|
|
|
uat->from_profile = from_profile;
|
2014-01-30 17:43:52 +00:00
|
|
|
/* Callers of uat_new() pass in (void*) for data_ptr, because
|
|
|
|
* that is the "universal" pointer type that can be cast to
|
|
|
|
* anything. However, for our purposes, we want a (void**).
|
|
|
|
* So, we cast (void*) data_ptr to (void**) here. That keeps
|
|
|
|
* gcc -fstrict-aliasing from complaining. */
|
|
|
|
uat->user_ptr = (void**) data_ptr;
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->nrows_p = numitems_ptr;
|
|
|
|
uat->copy_cb = copy_cb;
|
|
|
|
uat->update_cb = update_cb;
|
|
|
|
uat->free_cb = free_cb;
|
|
|
|
uat->post_update_cb = post_update_cb;
|
2016-12-21 10:50:47 +00:00
|
|
|
uat->reset_cb = reset_cb;
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->fields = flds_array;
|
2021-11-07 00:14:20 +00:00
|
|
|
uat->default_values = NULL;
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->user_data = g_array_new(FALSE,FALSE,(guint)uat->record_size);
|
2013-04-22 02:10:49 +00:00
|
|
|
uat->raw_data = g_array_new(FALSE,FALSE,(guint)uat->record_size);
|
|
|
|
uat->valid_data = g_array_new(FALSE,FALSE,sizeof(gboolean));
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->changed = FALSE;
|
|
|
|
uat->loaded = FALSE;
|
2011-10-09 09:55:14 +00:00
|
|
|
uat->from_global = FALSE;
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->rep = NULL;
|
|
|
|
uat->free_rep = NULL;
|
2016-12-21 10:50:47 +00:00
|
|
|
uat->help = g_strdup(help);
|
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
|
|
|
uat->flags = flags;
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
for (i=0;flds_array[i].title;i++) {
|
2020-12-21 02:30:28 +00:00
|
|
|
fld_data_t* f = g_new(fld_data_t, 1);
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
f->colnum = i+1;
|
|
|
|
f->rep = NULL;
|
|
|
|
f->free_rep = NULL;
|
|
|
|
|
|
|
|
flds_array[i].priv = f;
|
|
|
|
}
|
|
|
|
|
|
|
|
uat->ncols = i;
|
|
|
|
|
2014-01-30 17:43:52 +00:00
|
|
|
*((void**)data_ptr) = NULL;
|
2011-09-21 18:55:03 +00:00
|
|
|
*numitems_ptr = 0;
|
|
|
|
|
|
|
|
return uat;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
void* uat_add_record(uat_t* uat, const void* data, gboolean valid_rec) {
|
2011-09-21 18:55:03 +00:00
|
|
|
void* rec;
|
2013-04-22 02:10:49 +00:00
|
|
|
gboolean* valid;
|
2007-02-03 14:25:02 +00:00
|
|
|
|
2016-09-30 08:46:28 +00:00
|
|
|
uat_insert_record_idx(uat, uat->raw_data->len, data);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
if (valid_rec) {
|
|
|
|
/* Add a "known good" record to the list to be used by the dissector */
|
|
|
|
g_array_append_vals (uat->user_data, data, 1);
|
|
|
|
|
2015-02-14 14:36:09 +00:00
|
|
|
rec = UAT_USER_INDEX_PTR(uat, uat->user_data->len - 1);
|
2013-04-22 02:10:49 +00:00
|
|
|
|
|
|
|
if (uat->copy_cb) {
|
|
|
|
uat->copy_cb(rec, data, (unsigned int) uat->record_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
UAT_UPDATE(uat);
|
2016-09-30 08:46:28 +00:00
|
|
|
|
|
|
|
valid = &g_array_index(uat->valid_data, gboolean, uat->valid_data->len-1);
|
|
|
|
*valid = valid_rec;
|
2013-04-22 02:10:49 +00:00
|
|
|
} else {
|
|
|
|
rec = NULL;
|
|
|
|
}
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return rec;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2015-02-14 14:36:09 +00:00
|
|
|
/* Updates the validity of a record. */
|
2016-08-31 22:30:23 +00:00
|
|
|
void uat_update_record(uat_t *uat, const void *record, gboolean valid_rec) {
|
2015-02-14 14:36:09 +00:00
|
|
|
guint pos;
|
|
|
|
gboolean *valid;
|
|
|
|
|
|
|
|
/* Locate internal UAT data pointer. */
|
|
|
|
for (pos = 0; pos < uat->raw_data->len; pos++) {
|
2016-08-31 22:30:23 +00:00
|
|
|
if (UAT_INDEX_PTR(uat, pos) == record) {
|
2015-02-14 14:36:09 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pos == uat->raw_data->len) {
|
|
|
|
/* Data is not within list?! */
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2015-02-14 14:36:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
valid = &g_array_index(uat->valid_data, gboolean, pos);
|
|
|
|
*valid = valid_rec;
|
|
|
|
}
|
|
|
|
|
2007-02-04 05:19:02 +00:00
|
|
|
void uat_swap(uat_t* uat, guint a, guint b) {
|
2011-09-21 18:55:03 +00:00
|
|
|
size_t s = uat->record_size;
|
2015-01-10 00:50:09 +00:00
|
|
|
void* tmp;
|
2013-04-22 02:10:49 +00:00
|
|
|
gboolean tmp_bool;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert( a < uat->raw_data->len && b < uat->raw_data->len );
|
2007-02-04 05:19:02 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (a == b) return;
|
2007-02-04 05:19:02 +00:00
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
tmp = g_malloc(s);
|
2011-09-21 18:55:03 +00:00
|
|
|
memcpy(tmp, UAT_INDEX_PTR(uat,a), s);
|
|
|
|
memcpy(UAT_INDEX_PTR(uat,a), UAT_INDEX_PTR(uat,b), s);
|
|
|
|
memcpy(UAT_INDEX_PTR(uat,b), tmp, s);
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(tmp);
|
2007-02-04 05:19:02 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
tmp_bool = *(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (a)));
|
|
|
|
*(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (a))) = *(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (b)));
|
|
|
|
*(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (b))) = tmp_bool;
|
|
|
|
|
|
|
|
|
2007-02-04 05:19:02 +00:00
|
|
|
}
|
|
|
|
|
2016-09-30 08:46:28 +00:00
|
|
|
void uat_insert_record_idx(uat_t* uat, guint idx, const void *src_record) {
|
|
|
|
/* Allow insert before an existing item or append after the last item. */
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert( idx <= uat->raw_data->len );
|
2016-09-30 08:46:28 +00:00
|
|
|
|
|
|
|
/* Store a copy of the record and invoke copy_cb to clone pointers too. */
|
|
|
|
g_array_insert_vals(uat->raw_data, idx, src_record, 1);
|
|
|
|
void *rec = UAT_INDEX_PTR(uat, idx);
|
|
|
|
if (uat->copy_cb) {
|
|
|
|
uat->copy_cb(rec, src_record, (unsigned int) uat->record_size);
|
|
|
|
} else {
|
|
|
|
memcpy(rec, src_record, (unsigned int) uat->record_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initially assume that the record is invalid, it is not copied to the
|
|
|
|
* user-visible records list. */
|
|
|
|
gboolean valid_rec = FALSE;
|
|
|
|
g_array_insert_val(uat->valid_data, idx, valid_rec);
|
|
|
|
}
|
|
|
|
|
2007-01-28 10:31:32 +00:00
|
|
|
void uat_remove_record_idx(uat_t* uat, guint idx) {
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert( idx < uat->raw_data->len );
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_INDEX_PTR(uat,idx));
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
g_array_remove_index(uat->raw_data, idx);
|
|
|
|
g_array_remove_index(uat->valid_data, idx);
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2017-06-27 14:36:19 +00:00
|
|
|
void uat_move_index(uat_t * uat, guint old_idx, guint new_idx)
|
|
|
|
{
|
|
|
|
guint dir = 1;
|
|
|
|
guint start = old_idx;
|
|
|
|
if ( old_idx > new_idx )
|
|
|
|
dir = -1;
|
|
|
|
|
|
|
|
while ( start != new_idx )
|
|
|
|
{
|
|
|
|
uat_swap(uat, start, start + dir);
|
|
|
|
start += dir;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-26 19:03:01 +00:00
|
|
|
/* The returned filename was g_malloc()'d so the caller must free it */
|
2007-01-28 10:31:32 +00:00
|
|
|
gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
|
2011-10-09 09:55:14 +00:00
|
|
|
gchar *pers_fname = NULL;
|
2008-02-26 19:03:01 +00:00
|
|
|
|
2011-10-09 09:55:14 +00:00
|
|
|
if (! uat->from_global) {
|
2013-04-09 02:48:03 +00:00
|
|
|
pers_fname = get_persconffile_path(uat->filename, uat->from_profile);
|
2011-10-09 09:55:14 +00:00
|
|
|
}
|
2007-02-03 14:25:02 +00:00
|
|
|
|
2011-10-09 09:55:14 +00:00
|
|
|
if ((! for_writing ) && (! file_exists(pers_fname) )) {
|
2011-09-21 18:55:03 +00:00
|
|
|
gchar* data_fname = get_datafile_path(uat->filename);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-10-09 09:55:14 +00:00
|
|
|
if (file_exists(data_fname)) {
|
2011-09-21 18:55:03 +00:00
|
|
|
g_free(pers_fname);
|
|
|
|
return data_fname;
|
|
|
|
}
|
2008-02-26 19:03:01 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
g_free(data_fname);
|
|
|
|
g_free(pers_fname);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return pers_fname;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2008-01-30 22:50:55 +00:00
|
|
|
uat_t* uat_get_table_by_name(const char* name) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2008-01-30 22:50:55 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2011-09-21 18:55:03 +00:00
|
|
|
if ( g_str_equal(u->name,name) ) {
|
|
|
|
return (u);
|
|
|
|
}
|
|
|
|
}
|
2008-01-30 22:50:55 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return NULL;
|
2008-01-30 22:50:55 +00:00
|
|
|
}
|
|
|
|
|
2021-11-07 00:14:20 +00:00
|
|
|
void uat_set_default_values(uat_t *uat_in, const char *default_values[])
|
|
|
|
{
|
|
|
|
uat_in->default_values = default_values;
|
|
|
|
}
|
|
|
|
|
2017-05-15 13:07:34 +00:00
|
|
|
char *uat_fld_tostr(void *rec, uat_field_t *f) {
|
|
|
|
guint len;
|
|
|
|
char *ptr;
|
|
|
|
char *out;
|
|
|
|
|
|
|
|
f->cb.tostr(rec, &ptr, &len, f->cbdata.tostr, f->fld_data);
|
|
|
|
|
|
|
|
switch(f->mode) {
|
|
|
|
case PT_TXTMOD_NONE:
|
|
|
|
case PT_TXTMOD_STRING:
|
|
|
|
case PT_TXTMOD_ENUM:
|
2017-06-22 03:58:50 +00:00
|
|
|
case PT_TXTMOD_BOOL:
|
2017-05-15 13:07:34 +00:00
|
|
|
case PT_TXTMOD_FILENAME:
|
|
|
|
case PT_TXTMOD_DIRECTORYNAME:
|
2017-06-22 03:58:50 +00:00
|
|
|
case PT_TXTMOD_DISPLAY_FILTER:
|
2017-07-23 14:53:43 +00:00
|
|
|
case PT_TXTMOD_COLOR:
|
|
|
|
case PT_TXTMOD_PROTO_FIELD:
|
2017-05-15 13:07:34 +00:00
|
|
|
out = g_strndup(ptr, len);
|
|
|
|
break;
|
|
|
|
case PT_TXTMOD_HEXBYTES: {
|
|
|
|
GString *s = g_string_sized_new( len*2 + 1 );
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i=0; i<len;i++) g_string_append_printf(s, "%.2X", ((const guint8*)ptr)[i]);
|
|
|
|
|
|
|
|
out = g_strdup(s->str);
|
|
|
|
|
|
|
|
g_string_free(s, TRUE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2017-05-15 13:07:34 +00:00
|
|
|
out = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(ptr);
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
static void putfld(FILE* fp, void* rec, uat_field_t* f) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint fld_len;
|
2015-12-30 07:45:35 +00:00
|
|
|
char* fld_ptr;
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
f->cb.tostr(rec,&fld_ptr,&fld_len,f->cbdata.tostr,f->fld_data);
|
|
|
|
|
|
|
|
switch(f->mode){
|
2013-12-10 15:33:07 +00:00
|
|
|
case PT_TXTMOD_NONE:
|
2011-09-21 18:55:03 +00:00
|
|
|
case PT_TXTMOD_ENUM:
|
|
|
|
case PT_TXTMOD_FILENAME:
|
|
|
|
case PT_TXTMOD_DIRECTORYNAME:
|
2017-06-22 03:58:50 +00:00
|
|
|
case PT_TXTMOD_DISPLAY_FILTER:
|
2017-07-23 14:53:43 +00:00
|
|
|
case PT_TXTMOD_PROTO_FIELD:
|
|
|
|
case PT_TXTMOD_COLOR:
|
2011-09-21 18:55:03 +00:00
|
|
|
case PT_TXTMOD_STRING: {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
putc('"',fp);
|
|
|
|
|
|
|
|
for(i=0;i<fld_len;i++) {
|
|
|
|
char c = fld_ptr[i];
|
|
|
|
|
2014-05-13 12:44:47 +00:00
|
|
|
if (c == '"' || c == '\\' || ! g_ascii_isprint((guchar)c) ) {
|
2016-08-14 20:49:19 +00:00
|
|
|
fprintf(fp,"\\x%02x", (guchar) c);
|
2011-09-21 18:55:03 +00:00
|
|
|
} else {
|
|
|
|
putc(c,fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
putc('"',fp);
|
2015-01-10 00:50:09 +00:00
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
case PT_TXTMOD_HEXBYTES: {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for(i=0;i<fld_len;i++) {
|
2016-08-14 20:49:19 +00:00
|
|
|
fprintf(fp,"%02x", (guchar)fld_ptr[i]);
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2017-06-22 03:58:50 +00:00
|
|
|
case PT_TXTMOD_BOOL: {
|
|
|
|
fprintf(fp,"\"%s\"", fld_ptr);
|
|
|
|
break;
|
|
|
|
}
|
2011-09-21 18:55:03 +00:00
|
|
|
default:
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert_not_reached();
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2015-01-10 00:50:09 +00:00
|
|
|
|
2015-12-30 07:45:35 +00:00
|
|
|
g_free(fld_ptr);
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
gboolean uat_save(uat_t* uat, char** error) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
|
|
|
gchar* fname = uat_get_actual_filename(uat,TRUE);
|
|
|
|
FILE* fp;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (! fname ) return FALSE;
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
fp = ws_fopen(fname,"w");
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2009-02-11 11:04:30 +00:00
|
|
|
if (!fp && errno == ENOENT) {
|
|
|
|
/* Parent directory does not exist, try creating first */
|
|
|
|
gchar *pf_dir_path = NULL;
|
|
|
|
if (create_persconffile_dir(&pf_dir_path) != 0) {
|
2021-12-16 18:06:18 +00:00
|
|
|
*error = ws_strdup_printf("uat_save: error creating '%s'", pf_dir_path);
|
2009-02-11 11:04:30 +00:00
|
|
|
g_free (pf_dir_path);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
fp = ws_fopen(fname,"w");
|
|
|
|
}
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (!fp) {
|
2021-12-16 18:06:18 +00:00
|
|
|
*error = ws_strdup_printf("uat_save: error opening '%s': %s",fname,g_strerror(errno));
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*error = NULL;
|
|
|
|
g_free (fname);
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
/* Ensure raw_data is synced with user_data and all "good" entries have been accounted for */
|
|
|
|
|
|
|
|
/* Start by clearing current user_data */
|
|
|
|
for ( i = 0 ; i < uat->user_data->len ; i++ ) {
|
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_USER_INDEX_PTR(uat,i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_array_set_size(uat->user_data,0);
|
|
|
|
|
|
|
|
*((uat)->user_ptr) = NULL;
|
|
|
|
*((uat)->nrows_p) = 0;
|
|
|
|
|
|
|
|
/* Now copy "good" raw_data entries to user_data */
|
|
|
|
for ( i = 0 ; i < uat->raw_data->len ; i++ ) {
|
2015-02-14 14:36:09 +00:00
|
|
|
void *rec = UAT_INDEX_PTR(uat, i);
|
2016-09-30 08:46:28 +00:00
|
|
|
gboolean valid = g_array_index(uat->valid_data, gboolean, i);
|
|
|
|
if (valid) {
|
2013-04-22 02:10:49 +00:00
|
|
|
g_array_append_vals(uat->user_data, rec, 1);
|
|
|
|
if (uat->copy_cb) {
|
2015-02-14 14:36:09 +00:00
|
|
|
uat->copy_cb(UAT_USER_INDEX_PTR(uat, uat->user_data->len - 1),
|
|
|
|
rec, (unsigned int) uat->record_size);
|
2013-04-22 02:10:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UAT_UPDATE(uat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
fprintf(fp,"# This file is automatically generated, DO NOT MODIFY.\n");
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for ( i = 0 ; i < uat->user_data->len ; i++ ) {
|
|
|
|
void* rec = uat->user_data->data + (uat->record_size * i);
|
|
|
|
uat_field_t* f;
|
|
|
|
guint j;
|
2007-02-03 14:25:02 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
f = uat->fields;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for( j=0 ; j < uat->ncols ; j++ ) {
|
|
|
|
putfld(fp, rec, &(f[j]));
|
|
|
|
fputs((j == uat->ncols - 1) ? "\n" : "," ,fp);
|
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
fclose(fp);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->changed = FALSE;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return TRUE;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2008-02-15 22:36:24 +00:00
|
|
|
uat_t *uat_find(gchar *name) {
|
|
|
|
guint i;
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2008-02-15 22:36:24 +00:00
|
|
|
|
|
|
|
if (strcmp(u->name, name) == 0 || strcmp(u->filename, name) == 0) {
|
|
|
|
return u;
|
|
|
|
}
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2008-02-15 22:36:24 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-11 16:09:21 +00:00
|
|
|
void uat_clear(uat_t* uat) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2007-02-11 16:09:21 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for ( i = 0 ; i < uat->user_data->len ; i++ ) {
|
2013-04-22 02:10:49 +00:00
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_USER_INDEX_PTR(uat,i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i = 0 ; i < uat->raw_data->len ; i++ ) {
|
2011-09-21 18:55:03 +00:00
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_INDEX_PTR(uat,i));
|
|
|
|
}
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
g_array_set_size(uat->raw_data,0);
|
2011-09-21 18:55:03 +00:00
|
|
|
g_array_set_size(uat->user_data,0);
|
2013-04-22 02:10:49 +00:00
|
|
|
g_array_set_size(uat->valid_data,0);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*((uat)->user_ptr) = NULL;
|
|
|
|
*((uat)->nrows_p) = 0;
|
2016-12-21 10:50:47 +00:00
|
|
|
|
|
|
|
if (uat->reset_cb) {
|
|
|
|
uat->reset_cb();
|
|
|
|
}
|
2007-02-11 16:09:21 +00:00
|
|
|
}
|
|
|
|
|
2008-01-19 01:18:35 +00:00
|
|
|
void uat_unload_all(void) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2008-01-14 16:40:23 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2008-03-06 22:13:24 +00:00
|
|
|
/* Do not unload if not in profile */
|
|
|
|
if (u->from_profile) {
|
|
|
|
uat_clear(u);
|
|
|
|
u->loaded = FALSE;
|
|
|
|
}
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2008-01-14 16:40:23 +00:00
|
|
|
}
|
|
|
|
|
2016-12-21 10:50:47 +00:00
|
|
|
void uat_cleanup(void) {
|
|
|
|
guint i;
|
|
|
|
guint j;
|
|
|
|
uat_t* uat;
|
|
|
|
|
|
|
|
for (i = 0; i < all_uats->len; i++) {
|
|
|
|
uat = (uat_t *)g_ptr_array_index(all_uats, i);
|
|
|
|
uat_clear(uat);
|
|
|
|
g_free(uat->help);
|
|
|
|
g_free(uat->name);
|
|
|
|
g_free(uat->filename);
|
|
|
|
g_array_free(uat->user_data, TRUE);
|
|
|
|
g_array_free(uat->raw_data, TRUE);
|
|
|
|
g_array_free(uat->valid_data, TRUE);
|
|
|
|
for (j = 0; uat->fields[j].title; j++)
|
|
|
|
g_free(uat->fields[j].priv);
|
|
|
|
g_free(uat);
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
g_ptr_array_free(all_uats,TRUE);
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
2007-02-08 10:15:04 +00:00
|
|
|
|
|
|
|
void uat_foreach_table(uat_cb_t cb,void* user_data) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++)
|
|
|
|
cb(g_ptr_array_index(all_uats,i), user_data);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
|
|
|
}
|
2007-02-08 10:15:04 +00:00
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
void uat_load_all(void) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2015-01-10 00:50:09 +00:00
|
|
|
gchar* err;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2015-01-13 21:00:59 +00:00
|
|
|
if (!u->loaded) {
|
|
|
|
err = NULL;
|
2018-10-05 06:33:24 +00:00
|
|
|
if (!uat_load(u, NULL, &err)) {
|
2015-01-13 21:00:59 +00:00
|
|
|
report_failure("Error loading table '%s': %s",u->name,err);
|
|
|
|
g_free(err);
|
|
|
|
}
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2007-02-08 10:15:04 +00:00
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_str(void* u1 _U_, const char* strptr, guint len _U_, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2011-09-21 18:55:03 +00:00
|
|
|
if (strptr == NULL) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("NULL pointer");
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_oid(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2010-06-28 09:30:15 +00:00
|
|
|
unsigned int i;
|
2011-09-21 18:55:03 +00:00
|
|
|
*err = NULL;
|
|
|
|
|
|
|
|
if (strptr == NULL) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("NULL pointer");
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
BER: Fix segmentation fault when configuring new OIDs
Program terminated with signal 11, Segmentation fault.
#0 0x00007f573e5bdecf in uat_fld_chk_oid (u1=0x2eb1830, strptr=0x7f573c8431e4 "", len=0, u2=0x0, u3=0x0, err=0x7ffee1668748) at uat.c:494
494 if(strptr[len-1] == '.') {
(gdb)
(gdb) bt
#0 0x00007f573e5bdecf in uat_fld_chk_oid (u1=0x2eb1830, strptr=0x7f573c8431e4 "", len=0, u2=0x0, u3=0x0, err=0x7ffee1668748) at uat.c:494
#1 0x0000000000485dfc in uat_dlg_cb (win=0x3844290, user_data=0x3632bc0) at uat_gui.c:364
#2 0x00007f573b2f19a7 in _g_closure_invoke_va (closure=0x3367130, return_value=0x0, instance=0x3844290, args=0x7ffee1668a78, n_params=0,
Change-Id: Ic61480f8c1f2cd833c58de0b2acc24dcb831578f
Reviewed-on: https://code.wireshark.org/review/16800
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Stig Bjørlykke <stig@bjorlykke.org>
2016-07-31 13:59:01 +00:00
|
|
|
if (len == 0) {
|
|
|
|
*err = g_strdup("Empty OID");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for(i = 0; i < len; i++)
|
2014-10-17 23:10:53 +00:00
|
|
|
if(!(g_ascii_isdigit(strptr[i]) || strptr[i] == '.')) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("Only digits [0-9] and \".\" allowed in an OID");
|
|
|
|
return FALSE;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
if(strptr[len-1] == '.') {
|
|
|
|
*err = g_strdup("OIDs must not be terminated with a \".\"");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
if(!((*strptr == '0' || *strptr == '1' || *strptr =='2') && (len > 1 && strptr[1] == '.'))) {
|
|
|
|
*err = g_strdup("OIDs must start with \"0.\" (ITU-T assigned), \"1.\" (ISO assigned) or \"2.\" (joint ISO/ITU-T assigned)");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
/* should also check that the second arc is in the range 0-39 */
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return *err == NULL;
|
2010-06-28 09:30:15 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_proto(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2011-09-21 18:55:03 +00:00
|
|
|
if (len) {
|
2015-01-10 00:50:09 +00:00
|
|
|
char* name = g_strndup(strptr,len);
|
2011-09-21 18:55:03 +00:00
|
|
|
ascii_strdown_inplace(name);
|
|
|
|
g_strchug(name);
|
|
|
|
|
|
|
|
if (find_dissector(name)) {
|
|
|
|
*err = NULL;
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(name);
|
2011-09-21 18:55:03 +00:00
|
|
|
return TRUE;
|
|
|
|
} else {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("dissector not found");
|
|
|
|
g_free(name);
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2007-02-07 20:45:14 +00:00
|
|
|
}
|
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
static gboolean uat_fld_chk_num_check_result(gboolean result, const char* strn, char** err) {
|
|
|
|
if (result && ((*strn != '\0') && (*strn != ' '))) {
|
|
|
|
/* string valid, but followed by something other than a space */
|
|
|
|
result = FALSE;
|
|
|
|
errno = EINVAL;
|
|
|
|
}
|
|
|
|
if (!result) {
|
|
|
|
switch (errno) {
|
|
|
|
|
|
|
|
case EINVAL:
|
|
|
|
*err = g_strdup("Invalid value");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ERANGE:
|
|
|
|
*err = g_strdup("Value too large");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
*err = g_strdup(g_strerror(errno));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
static gboolean uat_fld_chk_num(int base, const char* strptr, guint len, char** err) {
|
2009-03-08 22:36:43 +00:00
|
|
|
if (len > 0) {
|
2018-10-20 20:36:56 +00:00
|
|
|
char* str = g_strndup(strptr, len);
|
|
|
|
const char* strn;
|
|
|
|
gboolean result;
|
|
|
|
guint32 value;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2018-10-20 20:36:56 +00:00
|
|
|
result = ws_basestrtou32(str, &strn, &value, base);
|
2021-01-04 20:59:23 +00:00
|
|
|
result = uat_fld_chk_num_check_result(result, strn, err);
|
|
|
|
g_free(str);
|
|
|
|
return result;
|
|
|
|
}
|
2015-01-10 00:50:09 +00:00
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2018-10-20 20:36:56 +00:00
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
static gboolean uat_fld_chk_num64(int base, const char* strptr, guint len, char** err) {
|
|
|
|
if (len > 0) {
|
|
|
|
char* str = g_strndup(strptr, len);
|
|
|
|
const char* strn;
|
|
|
|
gboolean result;
|
|
|
|
guint64 value64;
|
2018-10-20 20:36:56 +00:00
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
result = ws_basestrtou64(str, &strn, &value64, base);
|
|
|
|
result = uat_fld_chk_num_check_result(result, strn, err);
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(str);
|
2018-10-20 20:36:56 +00:00
|
|
|
return result;
|
2009-03-08 22:36:43 +00:00
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
2007-02-07 20:45:14 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_num_dec(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2014-11-19 03:53:32 +00:00
|
|
|
return uat_fld_chk_num(10, strptr, len, err);
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_num_hex(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2018-10-20 20:36:56 +00:00
|
|
|
return uat_fld_chk_num(16, strptr, len, err);
|
|
|
|
}
|
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
gboolean uat_fld_chk_num_dec64(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
return uat_fld_chk_num64(10, strptr, len, err);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean uat_fld_chk_num_hex64(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
return uat_fld_chk_num64(16, strptr, len, err);
|
|
|
|
}
|
|
|
|
|
2018-10-20 20:36:56 +00:00
|
|
|
gboolean uat_fld_chk_num_signed_dec(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2018-08-21 14:05:48 +00:00
|
|
|
if (len > 0) {
|
2018-10-20 20:36:56 +00:00
|
|
|
char* str = g_strndup(strptr,len);
|
2018-10-20 05:57:35 +00:00
|
|
|
const char* strn;
|
2018-08-21 14:05:48 +00:00
|
|
|
gboolean result;
|
2018-10-20 20:36:56 +00:00
|
|
|
gint32 value;
|
2018-08-21 14:05:48 +00:00
|
|
|
|
2018-10-20 20:36:56 +00:00
|
|
|
result = ws_strtoi32(str, &strn, &value);
|
2021-01-04 20:59:23 +00:00
|
|
|
result = uat_fld_chk_num_check_result(result, strn, err);
|
|
|
|
g_free(str);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2018-10-20 05:57:35 +00:00
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2018-10-20 05:57:35 +00:00
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
gboolean uat_fld_chk_num_signed_dec64(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
if (len > 0) {
|
|
|
|
char* str = g_strndup(strptr, len);
|
|
|
|
const char* strn;
|
|
|
|
gboolean result;
|
|
|
|
gint64 value;
|
2018-10-20 05:57:35 +00:00
|
|
|
|
2021-01-04 20:59:23 +00:00
|
|
|
result = ws_strtoi64(str, &strn, &value);
|
|
|
|
result = uat_fld_chk_num_check_result(result, strn, err);
|
2018-08-21 14:05:48 +00:00
|
|
|
g_free(str);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2017-06-22 03:58:50 +00:00
|
|
|
gboolean uat_fld_chk_bool(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err)
|
|
|
|
{
|
|
|
|
char* str = g_strndup(strptr,len);
|
|
|
|
|
|
|
|
if ((g_strcmp0(str, "TRUE") == 0) ||
|
|
|
|
(g_strcmp0(str, "FALSE") == 0)) {
|
|
|
|
*err = NULL;
|
|
|
|
g_free(str);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("invalid value: %s (must be TRUE or FALSE)", str);
|
2017-06-22 03:58:50 +00:00
|
|
|
g_free(str);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_enum(void* u1 _U_, const char* strptr, guint len, const void* v, const void* u3 _U_, char** err) {
|
2015-01-10 00:50:09 +00:00
|
|
|
char* str = g_strndup(strptr,len);
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2013-03-18 20:44:36 +00:00
|
|
|
const value_string* vs = (const value_string *)v;
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
for(i=0;vs[i].strptr;i++) {
|
2017-06-22 03:58:50 +00:00
|
|
|
if (g_strcmp0(vs[i].strptr,str) == 0) {
|
2011-09-21 18:55:03 +00:00
|
|
|
*err = NULL;
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(str);
|
2011-09-21 18:55:03 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("invalid value: %s",str);
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(str);
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_range(void* u1 _U_, const char* strptr, guint len, const void* v _U_, const void* u3, char** err) {
|
2015-01-10 00:50:09 +00:00
|
|
|
char* str = g_strndup(strptr,len);
|
2011-09-21 18:55:03 +00:00
|
|
|
range_t* r = NULL;
|
2016-12-22 20:12:27 +00:00
|
|
|
convert_ret_t ret = range_convert_str(NULL, &r, str,GPOINTER_TO_UINT(u3));
|
2015-01-10 00:50:09 +00:00
|
|
|
gboolean ret_value = FALSE;
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
switch ( ret ) {
|
|
|
|
case CVT_NO_ERROR:
|
|
|
|
*err = NULL;
|
2015-01-10 00:50:09 +00:00
|
|
|
ret_value = TRUE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
case CVT_SYNTAX_ERROR:
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("syntax error in range: %s",str);
|
2015-01-10 00:50:09 +00:00
|
|
|
ret_value = FALSE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
case CVT_NUMBER_TOO_BIG:
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("value too large in range: '%s' (max = %u)",str,GPOINTER_TO_UINT(u3));
|
2015-01-10 00:50:09 +00:00
|
|
|
ret_value = FALSE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
default:
|
2017-02-19 18:58:47 +00:00
|
|
|
*err = g_strdup("Unable to convert range. Please report this to wireshark-dev@wireshark.org");
|
2015-01-10 00:50:09 +00:00
|
|
|
ret_value = FALSE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2015-01-10 00:50:09 +00:00
|
|
|
|
|
|
|
g_free(str);
|
2016-12-22 20:12:27 +00:00
|
|
|
wmem_free(NULL, r);
|
2015-01-10 00:50:09 +00:00
|
|
|
return ret_value;
|
2007-04-03 19:08:00 +00:00
|
|
|
}
|
|
|
|
|
2017-07-23 14:53:43 +00:00
|
|
|
gboolean uat_fld_chk_color(void* u1 _U_, const char* strptr, guint len, const void* v _U_, const void* u3 _U_, char** err) {
|
|
|
|
|
|
|
|
if ((len != 7) || (*strptr != '#')) {
|
|
|
|
*err = g_strdup("Color must be of the format #RRGGBB");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Color is just # followed by hex string, so use hex verification */
|
|
|
|
return uat_fld_chk_num(16, strptr + 1, len - 1, err);
|
|
|
|
}
|
|
|
|
|
2007-04-01 14:55:25 +00:00
|
|
|
char* uat_unbinstring(const char* si, guint in_len, guint* len_p) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint8* buf;
|
|
|
|
guint len = in_len/2;
|
|
|
|
int i = 0;
|
|
|
|
int d0, d1;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (in_len%2) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-03-18 20:44:36 +00:00
|
|
|
buf= (guint8 *)g_malloc0(len+1);
|
2011-09-21 18:55:03 +00:00
|
|
|
if (len_p) *len_p = len;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
while(in_len) {
|
2014-01-08 00:28:13 +00:00
|
|
|
d1 = ws_xton(*(si++));
|
|
|
|
d0 = ws_xton(*(si++));
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
buf[i++] = (d1 * 16) + d0;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
in_len -= 2;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return (char*)buf;
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char* uat_unesc(const char* si, guint in_len, guint* len_p) {
|
2013-03-18 20:44:36 +00:00
|
|
|
char* buf = (char *)g_malloc0(in_len+1);
|
2011-09-21 18:55:03 +00:00
|
|
|
char* p = buf;
|
|
|
|
guint len = 0;
|
|
|
|
const char* s;
|
|
|
|
const char* in_end = si+in_len;
|
|
|
|
|
2019-01-03 16:53:42 +00:00
|
|
|
for (s = si; s < in_end; s++) {
|
2011-09-21 18:55:03 +00:00
|
|
|
switch(*s) {
|
|
|
|
case '\\':
|
|
|
|
switch(*(++s)) {
|
|
|
|
case 'a': *(p++) = '\a'; len++; break;
|
|
|
|
case 'b': *(p++) = '\b'; len++; break;
|
|
|
|
case 'e': *(p++) = '\033' /* '\e' is non ANSI-C */; len++; break;
|
|
|
|
case 'f': *(p++) = '\f'; len++; break;
|
|
|
|
case 'n': *(p++) = '\n'; len++; break;
|
|
|
|
case 'r': *(p++) = '\r'; len++; break;
|
|
|
|
case 't': *(p++) = '\t'; len++; break;
|
|
|
|
case 'v': *(p++) = '\v'; len++; break;
|
|
|
|
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
{
|
|
|
|
int c0 = 0;
|
|
|
|
int c1 = 0;
|
|
|
|
int c2 = 0;
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
c0 = (*s) - '0';
|
|
|
|
|
|
|
|
if ( s[1] >= '0' && s[1] <= '7' ) {
|
|
|
|
c1 = c0;
|
|
|
|
c0 = (*++s) - '0';
|
|
|
|
|
|
|
|
if ( s[1] >= '0' && s[1] <= '7' ) {
|
|
|
|
c2 = c1;
|
|
|
|
c1 = c0;
|
|
|
|
c0 = (*++s) - '0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c = (64 * c2) + (8 * c1) + c0;
|
|
|
|
*(p++) = (char) (c > 255 ? 255 : c);
|
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'x':
|
|
|
|
{
|
|
|
|
char c1 = *(s+1);
|
|
|
|
char c0 = *(s+2);
|
|
|
|
|
2014-10-17 23:10:53 +00:00
|
|
|
if (g_ascii_isxdigit(c1) && g_ascii_isxdigit(c0)) {
|
2014-01-08 00:28:13 +00:00
|
|
|
*(p++) = (ws_xton(c1) * 0x10) + ws_xton(c0);
|
2011-09-21 18:55:03 +00:00
|
|
|
s += 2;
|
|
|
|
} else {
|
|
|
|
*(p++) = *s;
|
|
|
|
}
|
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
*p++ = *s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*(p++) = *s;
|
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len_p) *len_p = len;
|
|
|
|
return buf;
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char* uat_undquote(const char* si, guint in_len, guint* len_p) {
|
2011-09-21 18:55:03 +00:00
|
|
|
return uat_unesc(si+1,in_len-2,len_p);
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char* uat_esc(const char* buf, guint len) {
|
2013-12-21 17:34:41 +00:00
|
|
|
const guint8* end = ((const guint8*)buf)+len;
|
2015-01-10 00:50:09 +00:00
|
|
|
char* out = (char *)g_malloc0((4*len)+1);
|
2011-09-21 18:55:03 +00:00
|
|
|
const guint8* b;
|
|
|
|
char* s = out;
|
|
|
|
|
2013-12-21 17:34:41 +00:00
|
|
|
for (b = (const guint8 *)buf; b < end; b++) {
|
2015-07-20 17:02:08 +00:00
|
|
|
if (*b == '"' || *b == '\\' || ! g_ascii_isprint(*b) ) {
|
2021-12-16 18:06:18 +00:00
|
|
|
snprintf(s,5,"\\x%02x",((guint)*b));
|
2011-09-21 18:55:03 +00:00
|
|
|
s+=4;
|
2015-07-20 17:02:08 +00:00
|
|
|
} else {
|
|
|
|
*(s++) = (*b);
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
2015-10-27 23:24:01 +00:00
|
|
|
gboolean uat_fld_chk_str_isprint(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2016-08-14 20:49:19 +00:00
|
|
|
char c = strptr[i];
|
|
|
|
if (! g_ascii_isprint(c)) {
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("invalid char pos=%d value=%02x", i, (guchar) c);
|
2015-10-27 23:24:01 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean uat_fld_chk_str_isalpha(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2016-08-14 20:49:19 +00:00
|
|
|
char c = strptr[i];
|
|
|
|
if (! g_ascii_isalpha(c)) {
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("invalid char pos=%d value=%02x", i, (guchar) c);
|
2015-10-27 23:24:01 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean uat_fld_chk_str_isalnum(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2016-08-14 20:49:19 +00:00
|
|
|
char c = strptr[i];
|
|
|
|
if (! g_ascii_isalnum(c)) {
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("invalid char pos=%d value=%02x", i, (guchar) c);
|
2015-10-27 23:24:01 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean uat_fld_chk_str_isdigit(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2016-08-14 20:49:19 +00:00
|
|
|
char c = strptr[i];
|
|
|
|
if (! g_ascii_isdigit(c)) {
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("invalid char pos=%d value=%02x", i, (guchar) c);
|
2015-10-27 23:24:01 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean uat_fld_chk_str_isxdigit(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
2016-08-14 20:49:19 +00:00
|
|
|
char c = strptr[i];
|
|
|
|
if (! g_ascii_isxdigit(c)) {
|
2021-12-16 18:06:18 +00:00
|
|
|
*err = ws_strdup_printf("invalid char pos=%d value=%02x", i, (guchar) c);
|
2015-10-27 23:24:01 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
|
2008-02-15 22:36:24 +00:00
|
|
|
/*
|
|
|
|
* Editor modelines
|
|
|
|
*
|
|
|
|
* Local Variables:
|
|
|
|
* c-basic-offset: 4
|
2011-09-21 18:55:03 +00:00
|
|
|
* tab-width: 8
|
2008-02-15 22:36:24 +00:00
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
2011-09-21 18:55:03 +00:00
|
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
2008-02-15 22:36:24 +00:00
|
|
|
*/
|