1 /* 2 * uat.h 3 * 4 * User Accessible Tables 5 * Maintain an array of user accessible data structures 6 * 7 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org> 8 * 9 * Wireshark - Network traffic analyzer 10 * By Gerald Combs <gerald@wireshark.org> 11 * Copyright 2001 Gerald Combs 12 * 13 * SPDX-License-Identifier: GPL-2.0-or-later 14 */ 15 16 #ifndef __UAT_H__ 17 #define __UAT_H__ 18 19 #include <stdlib.h> 20 21 #include "ws_symbol_export.h" 22 #include <wsutil/strtoi.h> 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif /* __cplusplus */ 27 28 /* 29 * UAT maintains a dynamically allocated table accessible to the user 30 * via a file and/or via GUI preference dialogs. 31 * 32 * The file is read from and written in the personal configuration directory. If 33 * there is no such file, defaults will be loaded from the global data 34 * directory. 35 * 36 * The behaviour of the table is controlled by a series of callbacks which 37 * the caller (e.g. a dissector) must provide. 38 * 39 * BEWARE that the user can change an UAT at (almost) any time (via the GUI). 40 * That is, pointers to records in an UAT are valid only during the call 41 * to the function that obtains them (do not store pointers to these records). 42 * The records contents are only guaranteed to be valid in the post_update_cb 43 * function. (Implementation detail: currently a race condition is possible 44 * where the UAT consumer (dissector code) tries to use the UAT while the GUI 45 * user frees a record resulting in use-after-free. This is not ideal and might 46 * be fixed later.) 47 * 48 * UATs are meant for short tables of user data (passwords and such), there is 49 * no quick access, you must iterate through them each time to fetch the record 50 * you are looking for. 51 * 52 * Only users via GUI or editing the file can add/remove records, your 53 * (dissector) code cannot. 54 */ 55 56 /* obscure data type to handle an uat */ 57 typedef struct epan_uat uat_t; 58 /******************************************** 59 * Callbacks: 60 * these instruct uat on how to deal with user info and data in records 61 ********************************************/ 62 63 /******** 64 * Callbacks dealing with the entire table 65 ********/ 66 67 /* 68 * Post-Update CB 69 * 70 * To be called by the GUI code after to the table has being edited. 71 * Will be called once the user clicks the Apply or OK button 72 * optional 73 */ 74 typedef void (*uat_post_update_cb_t)(void); 75 76 77 /******** 78 * Callbacks dealing with records (these deal with entire records) 79 ********/ 80 81 /** 82 * Copy CB 83 * copy(dest, source, len) 84 * 85 * Used to duplicate the contents of one record to another. 86 * Optional, memcpy will be used if not given. 87 */ 88 typedef void* (*uat_copy_cb_t)(void *dest, const void *source, size_t len); 89 90 /** 91 * Free CB 92 * free(record) 93 * 94 * Destroy the contents of a record, possibly freeing some fields. 95 * Do not free the container itself, this memory is owned by the UAT core. 96 * Optional if the record contains no pointers that need to be freed. 97 */ 98 typedef void (*uat_free_cb_t)(void *record); 99 100 /** 101 * Reset DB 102 * 103 * Used to free resources associated with a UAT loaded from file (e.g. post_update_cb) 104 * Optional. 105 */ 106 typedef void (*uat_reset_cb_t)(void); 107 108 /** 109 * Update CB 110 * update(record,&error) 111 * 112 * Validates the contents of the record contents, to be called after any record 113 * fields had been updated (either from file or after modifications in the GUI). 114 * 115 * Optional, the record will be considered valid if the callback is omitted. 116 * It must return TRUE if the contents are considered valid and FALSE otherwise 117 * in which case the failure reason is set in 'error'. The error string will be 118 * freed by g_free. 119 */ 120 typedef gboolean (*uat_update_cb_t)(void *record, char **error); 121 122 123 /******* 124 * Callbacks for single fields (these deal with single values) 125 * the caller should provide one of these for every field! 126 ********/ 127 128 /* 129 * Check CB 130 * chk(record, ptr, len, chk_data, fld_data, &error) 131 * 132 * given an input string (ptr, len) checks if the value is OK for a field in the record. 133 * it will return TRUE if OK or else 134 * it will return FALSE and set *error to inform the user on what's 135 * wrong with the given input 136 * The error string must be allocated with g_malloc() or 137 * a routine that calls it. 138 * optional, if not given any input is considered OK and the set cb will be called 139 */ 140 typedef gboolean (*uat_fld_chk_cb_t)(void *record, const char *ptr, unsigned len, const void *chk_data, const void *fld_data, char **error); 141 142 /* 143 * Set Field CB 144 * set(record, ptr, len, set_data, fld_data) 145 * 146 * given an input string (ptr, len) sets the value of a field in the record, 147 * it is mandatory 148 */ 149 typedef void (*uat_fld_set_cb_t)(void *record, const char *ptr, unsigned len, const void *set_data, const void *fld_data); 150 151 /* 152 * Convert-to-string CB 153 * tostr(record, &out_ptr, &out_len, tostr_data, fld_data) 154 * 155 * given a record returns a string representation of the field 156 * mandatory 157 */ 158 typedef void (*uat_fld_tostr_cb_t)(void *record, char **out_ptr, unsigned *out_len, const void *tostr_data, const void *fld_data); 159 160 /*********** 161 * Text Mode 162 * 163 * used for file and dialog representation of fields in columns, 164 * when the file is read it modifies the way the value is passed back to the fld_set_cb 165 * (see definition bellow for description) 166 ***********/ 167 168 typedef enum _uat_text_mode_t { 169 PT_TXTMOD_NONE, 170 /* not used */ 171 172 PT_TXTMOD_STRING, 173 /* 174 file: 175 reads: 176 ,"\x20\x00\x30", as " \00",3 ("space nil zero" of length 3) 177 ,"", as "",0 178 ,, as NULL,0 179 writes: 180 ,"\x20\x30\x00\x20", for " 0\0 ",4 181 ,"", for *, 0 182 ,, for NULL, * 183 dialog: 184 accepts \x?? and other escapes 185 gets "",0 on empty string 186 */ 187 PT_TXTMOD_HEXBYTES, 188 /* 189 file: 190 reads: 191 ,A1b2C3d4, as "\xa1\xb2\xc3\xd4",4 192 ,, as NULL,0 193 writes: 194 ,, on NULL, * 195 ,a1b2c3d4, on "\xa1\xb2\xc3\xd4",4 196 dialog: 197 interprets the following input ... as ...: 198 "a1b2c3d4" as "\xa1\xb2\xc3\xd4",4 199 "a1 b2:c3d4" as "\xa1\xb2\xc3\xd4",4 200 "" as NULL,0 201 "invalid" as NULL,3 202 "a1b" as NULL, 1 203 */ 204 PT_TXTMOD_ENUM, 205 /* Read/Writes/displays the string value (not number!) */ 206 207 PT_TXTMOD_COLOR, 208 /* Reads/Writes/display color in #RRGGBB format */ 209 210 PT_TXTMOD_FILENAME, 211 /* processed like a PT_TXTMOD_STRING, but shows a filename dialog */ 212 PT_TXTMOD_DIRECTORYNAME, 213 /* processed like a PT_TXTMOD_STRING, but shows a directory dialog */ 214 PT_TXTMOD_DISPLAY_FILTER, 215 /* processed like a PT_TXTMOD_STRING, but verifies display filter */ 216 PT_TXTMOD_PROTO_FIELD, 217 /* processed like a PT_TXTMOD_STRING, but verifies protocol field name (e.g tcp.flags.syn) */ 218 PT_TXTMOD_BOOL 219 /* Displays a checkbox for value */ 220 } uat_text_mode_t; 221 222 /* 223 * Fields 224 * 225 * 226 */ 227 typedef struct _uat_field_t { 228 const char* name; 229 const char* title; 230 uat_text_mode_t mode; 231 232 struct { 233 uat_fld_chk_cb_t chk; 234 uat_fld_set_cb_t set; 235 uat_fld_tostr_cb_t tostr; 236 } cb; 237 238 struct { 239 const void* chk; 240 const void* set; 241 const void* tostr; 242 } cbdata; 243 244 const void* fld_data; 245 246 const char* desc; 247 struct _fld_data_t* priv; 248 } uat_field_t; 249 250 #define FLDFILL NULL 251 #define UAT_END_FIELDS {NULL,NULL,PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,FLDFILL} 252 253 /* 254 * Flags to indicate what the settings in this UAT affect. 255 * This is used when UATs are changed interactively, to indicate what needs 256 * to be redone when the UAT is changed. 257 */ 258 #define UAT_AFFECTS_DISSECTION 0x00000001 /* affects packet dissection */ 259 #define UAT_AFFECTS_FIELDS 0x00000002 /* affects what named fields exist */ 260 261 /** Create a new UAT. 262 * 263 * @param name The name of the table 264 * @param size The size of the structure 265 * @param filename The filename to be used (either in userdir or datadir) 266 * @param from_profile TRUE if profile directory to be used 267 * @param data_ptr Although a void*, this is really a pointer to a null terminated array of pointers to the data 268 * @param num_items_ptr A pointer with number of items 269 * @param flags flags indicating what this UAT affects 270 * @param help A pointer to help text 271 * @param copy_cb A function that copies the data in the struct 272 * @param update_cb Will be called when a record is updated 273 * @param free_cb Will be called to destroy a struct in the dataset 274 * @param post_update_cb Will be called once the user clicks the Apply or OK button 275 * @param reset_cb Will be called to destroy internal data 276 * @param flds_array A pointer to an array of uat_field_t structs 277 * 278 * @return A freshly-allocated and populated uat_t struct. 279 */ 280 WS_DLL_PUBLIC 281 uat_t* uat_new(const char* name, 282 size_t size, 283 const char* filename, 284 gboolean from_profile, 285 void* data_ptr, 286 guint* num_items_ptr, 287 guint flags, 288 const char* help, 289 uat_copy_cb_t copy_cb, 290 uat_update_cb_t update_cb, 291 uat_free_cb_t free_cb, 292 uat_post_update_cb_t post_update_cb, 293 uat_reset_cb_t reset_cb, 294 uat_field_t* flds_array); 295 296 /** Cleanup all UATs. 297 * 298 */ 299 void uat_cleanup(void); 300 301 /** Populate a UAT using its file. 302 * 303 * @param uat_in Pointer to a uat. Must not be NULL. 304 * @param filename Filename to load, NULL to fetch from current profile. 305 * @param err Upon failure, points to an error string. 306 * 307 * @return TRUE on success, FALSE on failure. 308 */ 309 WS_DLL_PUBLIC 310 gboolean uat_load(uat_t* uat_in, const gchar *filename, char** err); 311 312 /** Create or update a single UAT entry using a string. 313 * 314 * @param uat_in Pointer to a uat. Must not be NULL. 315 * @param entry The string representation of the entry. Format must match 316 * what's written to the uat's output file. 317 * @param err Upon failure, points to an error string. 318 * 319 * @return TRUE on success, FALSE on failure. 320 */ 321 gboolean uat_load_str(uat_t* uat_in, char* entry, char** err); 322 323 /** Given a UAT name or filename, find its pointer. 324 * 325 * @param name The name or filename of the uat 326 * 327 * @return A pointer to the uat on success, NULL on failure. 328 */ 329 uat_t *uat_find(gchar *name); 330 331 WS_DLL_PUBLIC 332 uat_t* uat_get_table_by_name(const char* name); 333 334 /** 335 * Provide default field values for a UAT. 336 * 337 * This can be used to provide forward compatibility when fields are added 338 * to a UAT. 339 * 340 * @param uat_in Pointer to a uat. Must not be NULL. 341 * @param default_values An array of strings with default values. Must 342 * be the same length as flds_array. Individual elements can be NULL, 343 * and can be used to distinguish between mandatory and optional fields, 344 * e.g. { NULL, NULL, NULL, "default value (optional)" } 345 * @todo Use this to provide default values for empty tables. 346 */ 347 WS_DLL_PUBLIC 348 void uat_set_default_values(uat_t *uat_in, const char *default_values[]); 349 350 /* 351 * Some common uat_fld_chk_cbs 352 */ 353 WS_DLL_PUBLIC 354 gboolean uat_fld_chk_str(void*, const char*, unsigned, const void*, const void*, char** err); 355 gboolean uat_fld_chk_oid(void*, const char*, unsigned, const void*, const void*, char** err); 356 WS_DLL_PUBLIC 357 gboolean uat_fld_chk_proto(void*, const char*, unsigned, const void*, const void*, char** err); 358 WS_DLL_PUBLIC 359 gboolean uat_fld_chk_num_dec(void*, const char*, unsigned, const void*, const void*, char** err); 360 WS_DLL_PUBLIC 361 gboolean uat_fld_chk_num_dec64(void*, const char*, unsigned, const void*, const void*, char** err); 362 WS_DLL_PUBLIC 363 gboolean uat_fld_chk_num_hex(void*, const char*, unsigned, const void*, const void*, char** err); 364 WS_DLL_PUBLIC 365 gboolean uat_fld_chk_num_hex64(void*, const char*, unsigned, const void*, const void*, char** err); 366 WS_DLL_PUBLIC 367 gboolean uat_fld_chk_num_signed_dec(void*, const char*, unsigned, const void*, const void*, char** err); 368 WS_DLL_PUBLIC 369 gboolean uat_fld_chk_num_signed_dec64(void*, const char*, unsigned, const void*, const void*, char** err); 370 WS_DLL_PUBLIC 371 gboolean uat_fld_chk_bool(void*, const char*, unsigned, const void*, const void*, char** err); 372 WS_DLL_PUBLIC 373 gboolean uat_fld_chk_enum(void*, const char*, unsigned, const void*, const void*, char**); 374 WS_DLL_PUBLIC 375 gboolean uat_fld_chk_range(void*, const char*, unsigned, const void*, const void*, char**); 376 WS_DLL_PUBLIC 377 gboolean uat_fld_chk_color(void*, const char*, unsigned, const void*, const void*, char**); 378 379 typedef void (*uat_cb_t)(void* uat,void* user_data); 380 WS_DLL_PUBLIC 381 void uat_foreach_table(uat_cb_t cb,void* user_data); 382 void uat_unload_all(void); 383 384 char* uat_undquote(const char* si, guint in_len, guint* len_p); 385 char* uat_unbinstring(const char* si, guint in_len, guint* len_p); 386 char* uat_unesc(const char* si, guint in_len, guint* len_p); 387 char* uat_esc(const char* buf, guint len); 388 389 /* Some strings entirely made of ... already declared */ 390 391 WS_DLL_PUBLIC 392 gboolean uat_fld_chk_str_isprint(void*, const char*, unsigned, const void*, const void*, char**); 393 394 WS_DLL_PUBLIC 395 gboolean uat_fld_chk_str_isalpha(void*, const char*, unsigned, const void*, const void*, char**); 396 397 WS_DLL_PUBLIC 398 gboolean uat_fld_chk_str_isalnum(void*, const char*, unsigned, const void*, const void*, char**); 399 400 WS_DLL_PUBLIC 401 gboolean uat_fld_chk_str_isdigit(void*, const char*, unsigned, const void*, const void*, char**); 402 403 WS_DLL_PUBLIC 404 gboolean uat_fld_chk_str_isxdigit(void*, const char*, unsigned, const void*, const void*, char**); 405 406 407 /* 408 * Macros 409 * to define basic uat_fld_set_cbs, uat_fld_tostr_cbs 410 * for those elements in uat_field_t array 411 */ 412 413 #ifdef __cplusplus 414 #define UNUSED_PARAMETER(n) 415 #else 416 #define UNUSED_PARAMETER(n) n _U_ 417 #endif 418 419 /* 420 * CSTRING macros, 421 * a simple c-string contained in (((rec_t*)rec)->(field_name)) 422 */ 423 #define UAT_CSTRING_CB_DEF(basename,field_name,rec_t) \ 424 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 425 char* new_buf = g_strndup(buf,len); \ 426 g_free((((rec_t*)rec)->field_name)); \ 427 (((rec_t*)rec)->field_name) = new_buf; } \ 428 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 429 if (((rec_t*)rec)->field_name ) { \ 430 *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \ 431 *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \ 432 } else { \ 433 *out_ptr = g_strdup(""); *out_len = 0; } } 434 435 #define UAT_FLD_CSTRING(basename,field_name,title,desc) \ 436 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 437 438 #define UAT_FLD_CSTRING_ISPRINT(basename,field_name,title,desc) \ 439 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_str_isprint,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 440 441 #define UAT_FLD_CSTRING_OTHER(basename,field_name,title,chk,desc) \ 442 {#field_name, title, PT_TXTMOD_STRING,{ chk ,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 443 444 /* 445 * FILENAME and DIRECTORYNAME, 446 * a simple c-string contained in (((rec_t*)rec)->(field_name)) 447 */ 448 #define UAT_FILENAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t) 449 450 /* XXX UAT_FLD_FILENAME is currently unused. */ 451 #define UAT_FLD_FILENAME(basename,field_name,title,desc) \ 452 {#field_name, title, PT_TXTMOD_FILENAME,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 453 454 /* 455 * Both the Qt and GTK+ UIs assume that we're opening a preexisting 456 * file. We might want to split the ..._FILENAME defines into 457 * ..._FILE_OPEN and ..._FILE_SAVE if we ever need to specify a 458 * file that we're creating. 459 */ 460 #define UAT_FLD_FILENAME_OTHER(basename,field_name,title,chk,desc) \ 461 {#field_name, title, PT_TXTMOD_FILENAME,{chk,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 462 463 #define UAT_DIRECTORYNAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t) 464 465 #define UAT_FLD_DIRECTORYNAME(basename,field_name,title,desc) \ 466 {#field_name, title, PT_TXTMOD_DIRECTORYNAME,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 467 468 /* 469 * DISPLAY_FILTER, 470 * a simple c-string contained in (((rec_t*)rec)->(field_name)) 471 */ 472 #define UAT_DISPLAY_FILTER_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t) 473 474 #define UAT_FLD_DISPLAY_FILTER(basename,field_name,title,desc) \ 475 {#field_name, title, PT_TXTMOD_DISPLAY_FILTER, {uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 476 477 /* 478 * PROTO_FIELD, 479 * a simple c-string contained in (((rec_t*)rec)->(field_name)) 480 */ 481 #define UAT_PROTO_FIELD_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t) 482 483 #define UAT_FLD_PROTO_FIELD(basename,field_name,title,desc) \ 484 {#field_name, title, PT_TXTMOD_PROTO_FIELD, {uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 485 486 /* 487 * OID - just a CSTRING with a specific check routine 488 */ 489 #define UAT_FLD_OID(basename,field_name,title,desc) \ 490 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_oid,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 491 492 493 /* 494 * LSTRING MACROS 495 */ 496 #define UAT_LSTRING_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \ 497 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 498 char* new_val = uat_unesc(buf,len,&(((rec_t*)rec)->len_element)); \ 499 g_free((((rec_t*)rec)->ptr_element)); \ 500 (((rec_t*)rec)->ptr_element) = new_val; }\ 501 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 502 if (((rec_t*)rec)->ptr_element ) { \ 503 *out_ptr = uat_esc(((rec_t*)rec)->ptr_element, (((rec_t*)rec)->len_element)); \ 504 *out_len = (unsigned)strlen(*out_ptr); \ 505 } else { \ 506 *out_ptr = g_strdup(""); \ 507 *out_len = 0; \ 508 } \ 509 } 510 511 #define UAT_FLD_LSTRING(basename,field_name,title, desc) \ 512 {#field_name, title, PT_TXTMOD_STRING,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 513 514 515 /* 516 * BUFFER macros, 517 * a buffer_ptr contained in (((rec_t*)rec)->(field_name)) 518 * and its len in (((rec_t*)rec)->(len_name)) 519 */ 520 #define UAT_BUFFER_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \ 521 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 522 char* new_buf = len ? (char *)g_memdup2(buf,len) : NULL; \ 523 g_free((((rec_t*)rec)->ptr_element)); \ 524 (((rec_t*)rec)->ptr_element) = new_buf; \ 525 (((rec_t*)rec)->len_element) = len; } \ 526 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 527 *out_ptr = ((rec_t*)rec)->ptr_element ? (char*)g_memdup2(((rec_t*)rec)->ptr_element,((rec_t*)rec)->len_element) : g_strdup(""); \ 528 *out_len = ((rec_t*)rec)->len_element; } 529 530 #define UAT_FLD_BUFFER(basename,field_name,title,desc) \ 531 {#field_name, title, PT_TXTMOD_HEXBYTES,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 532 533 534 /* 535 * DEC Macros, 536 * an unsigned decimal number contained in (((rec_t*)rec)->(field_name)) 537 */ 538 #define UAT_DEC_CB_DEF(basename,field_name,rec_t) \ 539 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 540 char* tmp_str = g_strndup(buf,len); \ 541 ws_strtou32(tmp_str, NULL, &((rec_t*)rec)->field_name); \ 542 g_free(tmp_str); } \ 543 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 544 *out_ptr = g_strdup_printf("%u",((rec_t*)rec)->field_name); \ 545 *out_len = (unsigned)strlen(*out_ptr); } 546 547 #define UAT_FLD_DEC(basename,field_name,title,desc) \ 548 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 549 550 /* 551 * an unsigned 64bit decimal number contained in (((rec_t*)rec)->(field_name)) 552 */ 553 #define UAT_DEC64_CB_DEF(basename,field_name,rec_t) \ 554 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 555 char* tmp_str = g_strndup(buf,len); \ 556 ws_strtou64(tmp_str, NULL, &((rec_t*)rec)->field_name); \ 557 g_free(tmp_str); } \ 558 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 559 *out_ptr = g_strdup_printf("%" G_GINT64_MODIFIER "u",((rec_t*)rec)->field_name); \ 560 *out_len = (unsigned)strlen(*out_ptr); } 561 562 #define UAT_FLD_DEC64(basename,field_name,title,desc) \ 563 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_dec64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 564 565 /* 566 * a *signed* decimal number contained in (((rec_t*)rec)->(field_name)) 567 */ 568 #define UAT_SIGNED_DEC_CB_DEF(basename,field_name,rec_t) \ 569 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 570 char* tmp_str = g_strndup(buf,len); \ 571 ws_strtoi32(tmp_str, NULL, &((rec_t*)rec)->field_name); \ 572 g_free(tmp_str); } \ 573 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 574 *out_ptr = g_strdup_printf("%d",((rec_t*)rec)->field_name); \ 575 *out_len = (unsigned)strlen(*out_ptr); } 576 577 #define UAT_FLD_SIGNED_DEC(basename,field_name,title,desc) \ 578 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_signed_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 579 580 /* 581 * and a *signed* 64bit decimal number contained in (((rec_t*)rec)->(field_name)) 582 */ 583 #define UAT_SIGNED_DEC64_CB_DEF(basename,field_name,rec_t) \ 584 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 585 char* tmp_str = g_strndup(buf,len); \ 586 ws_strtoi64(tmp_str, NULL, &((rec_t*)rec)->field_name); \ 587 g_free(tmp_str); } \ 588 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 589 *out_ptr = g_strdup_printf("%" G_GINT64_MODIFIER "d",((rec_t*)rec)->field_name); \ 590 *out_len = (unsigned)strlen(*out_ptr); } 591 592 #define UAT_FLD_SIGNED_DEC64(basename,field_name,title,desc) \ 593 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_signed_dec64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 594 595 #define UAT_FLD_NONE(basename,field_name,title,desc) \ 596 {#field_name, title, PT_TXTMOD_NONE,{uat_fld_chk_num_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 597 598 599 /* 600 * HEX Macros, 601 * an unsigned hexadecimal number contained in (((rec_t*)rec)->(field_name)) 602 */ 603 #define UAT_HEX_CB_DEF(basename,field_name,rec_t) \ 604 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 605 char* tmp_str = g_strndup(buf,len); \ 606 ws_hexstrtou32(tmp_str, NULL, &((rec_t*)rec)->field_name); \ 607 g_free(tmp_str); } \ 608 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 609 *out_ptr = g_strdup_printf("%x",((rec_t*)rec)->field_name); \ 610 *out_len = (unsigned)strlen(*out_ptr); } 611 612 #define UAT_FLD_HEX(basename,field_name,title,desc) \ 613 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_hex,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 614 615 /* 616 * HEX Macros for 64bit, 617 * an unsigned long long hexadecimal number contained in (((rec_t*)rec)->(field_name)) 618 */ 619 #define UAT_HEX64_CB_DEF(basename,field_name,rec_t) \ 620 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 621 char* tmp_str = g_strndup(buf,len); \ 622 ws_hexstrtou64(tmp_str, NULL, &((rec_t*)rec)->field_name); \ 623 g_free(tmp_str); } \ 624 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 625 *out_ptr = g_strdup_printf("%" G_GINT64_MODIFIER "x",((rec_t*)rec)->field_name); \ 626 *out_len = (unsigned)strlen(*out_ptr); } 627 628 #define UAT_FLD_HEX64(basename,field_name,title,desc) \ 629 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_hex64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 630 631 /* 632 * BOOL Macros, 633 * an boolean value contained in (((rec_t*)rec)->(field_name)) 634 */ 635 #define UAT_BOOL_CB_DEF(basename,field_name,rec_t) \ 636 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 637 char* tmp_str = g_strndup(buf,len); \ 638 if (g_strcmp0(tmp_str, "TRUE") == 0) \ 639 ((rec_t*)rec)->field_name = 1; \ 640 else \ 641 ((rec_t*)rec)->field_name = 0; \ 642 g_free(tmp_str); } \ 643 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 644 *out_ptr = g_strdup_printf("%s",((rec_t*)rec)->field_name ? "TRUE" : "FALSE"); \ 645 *out_len = (unsigned)strlen(*out_ptr); } 646 647 #define UAT_FLD_BOOL(basename,field_name,title,desc) \ 648 {#field_name, title, PT_TXTMOD_BOOL,{uat_fld_chk_bool,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 649 650 /* 651 * ENUM macros 652 * enum_t: name = ((enum_t*)ptr)->strptr 653 * value = ((enum_t*)ptr)->value 654 * rec_t: 655 * value 656 */ 657 #define UAT_VS_DEF(basename,field_name,rec_t,default_t,default_val,default_str) \ 658 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\ 659 guint i; \ 660 char* str = g_strndup(buf,len); \ 661 const char* cstr; \ 662 ((rec_t*)rec)->field_name = default_val; \ 663 for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \ 664 if (g_str_equal(cstr,str)) { \ 665 ((rec_t*)rec)->field_name = (default_t)((const value_string*)vs)[i].value; \ 666 g_free(str); \ 667 return; \ 668 } \ 669 } \ 670 g_free(str); } \ 671 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\ 672 guint i; \ 673 for(i=0;((const value_string*)vs)[i].strptr;i++) { \ 674 if ( ((const value_string*)vs)[i].value == ((rec_t*)rec)->field_name ) { \ 675 *out_ptr = g_strdup(((const value_string*)vs)[i].strptr); \ 676 *out_len = (unsigned)strlen(*out_ptr); \ 677 return; \ 678 } \ 679 } \ 680 *out_ptr = g_strdup(default_str); \ 681 *out_len = (unsigned)strlen(default_str); } 682 683 #define UAT_VS_CSTRING_DEF(basename,field_name,rec_t,default_val,default_str) \ 684 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\ 685 guint i; \ 686 char* str = g_strndup(buf,len); \ 687 const char* cstr; \ 688 ((rec_t*)rec)->field_name = default_val; \ 689 for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \ 690 if (g_str_equal(cstr,str)) { \ 691 ((rec_t*)rec)->field_name = g_strdup(((const value_string*)vs)[i].strptr); \ 692 g_free(str); \ 693 return; \ 694 } \ 695 } \ 696 g_free(str);} \ 697 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(vs), const void* UNUSED_PARAMETER(u2)) {\ 698 if (((rec_t*)rec)->field_name ) { \ 699 *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \ 700 *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \ 701 } else { \ 702 *out_ptr = g_strdup(""); *out_len = 0; } } 703 704 #define UAT_FLD_VS(basename,field_name,title,enum,desc) \ 705 {#field_name, title, PT_TXTMOD_ENUM,{uat_fld_chk_enum,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},&(enum),desc,FLDFILL} 706 707 708 /* 709 * Color Macros, 710 * an #RRGGBB color value contained in (((rec_t*)rec)->(field_name)) 711 */ 712 #define UAT_COLOR_CB_DEF(basename,field_name,rec_t) \ 713 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 714 if (len < 1) { \ 715 ((rec_t*)rec)->field_name = 0; \ 716 return; \ 717 } \ 718 char* tmp_str = g_strndup(buf+1,len-1); \ 719 ((rec_t*)rec)->field_name = (guint)strtol(tmp_str,NULL,16); \ 720 g_free(tmp_str); } \ 721 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 722 *out_ptr = g_strdup_printf("#%06X",((rec_t*)rec)->field_name); \ 723 *out_len = (unsigned)strlen(*out_ptr); } 724 725 #define UAT_FLD_COLOR(basename,field_name,title,desc) \ 726 {#field_name, title, PT_TXTMOD_COLOR,{uat_fld_chk_color,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 727 728 729 /* 730 * PROTO macros 731 */ 732 733 #define UAT_PROTO_DEF(basename, field_name, dissector_field, name_field, rec_t) \ 734 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 735 if (len) { \ 736 gchar *tmp = g_strndup(buf,len); \ 737 ((rec_t*)rec)->name_field = g_ascii_strdown(tmp, -1); \ 738 g_free(tmp); \ 739 g_strchug(((rec_t*)rec)->name_field); \ 740 ((rec_t*)rec)->dissector_field = find_dissector(((rec_t*)rec)->name_field); \ 741 } else { \ 742 ((rec_t*)rec)->dissector_field = find_dissector("data"); \ 743 ((rec_t*)rec)->name_field = NULL; \ 744 } } \ 745 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 746 if ( ((rec_t*)rec)->name_field ) { \ 747 *out_ptr = g_strdup((((rec_t*)rec)->name_field)); \ 748 *out_len = (unsigned)strlen(*out_ptr); \ 749 } else { \ 750 *out_ptr = g_strdup(""); *out_len = 0; } } 751 752 753 #define UAT_FLD_PROTO(basename,field_name,title,desc) \ 754 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_proto,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL} 755 756 /* 757 * RANGE macros 758 */ 759 760 #define UAT_RANGE_CB_DEF(basename,field_name,rec_t) \ 761 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* u2) {\ 762 char* rng = g_strndup(buf,len);\ 763 range_convert_str(NULL, &(((rec_t*)rec)->field_name), rng,GPOINTER_TO_UINT(u2)); \ 764 g_free(rng); \ 765 } \ 766 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\ 767 if ( ((rec_t*)rec)->field_name ) { \ 768 *out_ptr = range_convert_range(NULL, ((rec_t*)rec)->field_name); \ 769 *out_len = (unsigned)strlen(*out_ptr); \ 770 } else { \ 771 *out_ptr = g_strdup(""); *out_len = 0; } } 772 773 774 #define UAT_FLD_RANGE(basename,field_name,title,max,desc) \ 775 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_range,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},\ 776 {0,0,0},GUINT_TO_POINTER(max),desc,FLDFILL} 777 778 #ifdef __cplusplus 779 } 780 #endif /* __cplusplus */ 781 782 #endif /* __UAT_H__ */ 783