From 2da188667d37757ae999c8ab24ed35b64e08700c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 18 Jun 2019 20:40:11 -0400 Subject: [PATCH] Add new "struct_var_" functions to manipulate struct fields. These functions exist one level higher than typed_var_t. They describe a type, a name, and an offset within a structure. --- src/lib/conf/conftypes.h | 40 ++++++++ src/lib/confmgt/include.am | 2 + src/lib/confmgt/structvar.c | 200 ++++++++++++++++++++++++++++++++++++ src/lib/confmgt/structvar.h | 51 +++++++++ 4 files changed, 293 insertions(+) create mode 100644 src/lib/confmgt/structvar.c create mode 100644 src/lib/confmgt/structvar.h diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h index e66ab3d5aa..cddfeff2fd 100644 --- a/src/lib/conf/conftypes.h +++ b/src/lib/conf/conftypes.h @@ -63,8 +63,48 @@ typedef enum config_type_t { CONFIG_TYPE_ROUTERSET, /**< A list of router names, addrs, and fps, * parsed into a routerset_t. */ CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */ + CONFIG_TYPE_EXTENDED, /**< Extended type; definition will appear in + * pointer. */ } config_type_t; +/* Forward delcaration for var_type_def_t, for extended types. */ +struct var_type_def_t; + +/** Structure to specify a named, typed member within a structure. */ +typedef struct struct_member_t { + /** Name of the field. */ + const char *name; + /** Type of the field, according to the config_type_t enumeration. + * + * This value is CONFIG_TYPE_EXTENDED for any type not listed in + * config_type_t. + **/ + config_type_t type; + /** + * Pointer to a type definition for the type of this field. Overrides + * type if not NULL. + **/ + const struct var_type_def_t *type_def; + /** + * Offset of this field within the structure. Compute this with + * offsetof(structure, fieldname). + **/ + int offset; +} struct_member_t; + +/** + * Structure to describe the location and preferred value of a "magic number" + * field within a structure. + * + * These 'magic numbers' are 32-bit values used to tag objects to make sure + * that they have the correct type. + */ +typedef struct struct_magic_decl_t { + const char *typename; + uint32_t magic_val; + int magic_offset; +} struct_magic_decl_t; + #ifdef TOR_UNIT_TESTS /** * Union used when building in test mode typechecking the members of a type diff --git a/src/lib/confmgt/include.am b/src/lib/confmgt/include.am index a2c7649957..aa5b37fdb5 100644 --- a/src/lib/confmgt/include.am +++ b/src/lib/confmgt/include.am @@ -6,6 +6,7 @@ endif # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_confmgt_a_SOURCES = \ + src/lib/confmgt/structvar.c \ src/lib/confmgt/type_defs.c \ src/lib/confmgt/typedvar.c \ src/lib/confmgt/unitparse.c @@ -17,6 +18,7 @@ src_lib_libtor_confmgt_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ + src/lib/confmgt/structvar.h \ src/lib/confmgt/type_defs.h \ src/lib/confmgt/typedvar.h \ src/lib/confmgt/unitparse.h \ diff --git a/src/lib/confmgt/structvar.c b/src/lib/confmgt/structvar.c new file mode 100644 index 0000000000..7ea00fbde9 --- /dev/null +++ b/src/lib/confmgt/structvar.c @@ -0,0 +1,200 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file structvar.c + * @brief Functions to manipulate named and typed elements of + * a structure. + * + * These functions represent a low-level API for accessing a member of a + * structure. They use typedvar.c to work, and they are used in turn by the + * configuration system to examine and set fields in configuration objects + * used by individual modules. + * + * Almost no code should call these directly. + **/ + +#include "orconfig.h" +#include "lib/confmgt/structvar.h" +#include "lib/cc/compat_compiler.h" +#include "lib/conf/conftypes.h" +#include "lib/confmgt/type_defs.h" +#include "lib/confmgt/typedvar.h" +#include "lib/log/util_bug.h" + +#include + +/** + * Set the 'magic number' on object to correspond to decl. + **/ +void +struct_set_magic(void *object, const struct_magic_decl_t *decl) +{ + tor_assert(object); + tor_assert(decl); + uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset); + *ptr = decl->magic_val; +} + +/** + * Assert that the 'magic number' on object to corresponds to decl. + **/ +void +struct_check_magic(const void *object, const struct_magic_decl_t *decl) +{ + tor_assert(object); + tor_assert(decl); + + const uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset); + tor_assertf(*ptr == decl->magic_val, + "Bad magic number on purported %s object. " + "Expected %"PRIu32"x but got "PRIu32"x.", + decl->magic_val, *ptr); +} + +/** + * Return a mutable pointer to the member of object described + * by member. + **/ +void * +struct_get_mptr(void *object, const struct_member_t *member) +{ + tor_assert(object); + return STRUCT_VAR_P(object, member->offset); +} + +/** + * Return a const pointer to the member of object described + * by member. + **/ +const void * +struct_get_ptr(const void *object, const struct_member_t *member) +{ + tor_assert(object); + return STRUCT_VAR_P(object, member->offset); +} + +/** + * Helper: given a struct_member_t, look up the type definition for its + * variable. + */ +static const var_type_def_t * +get_type_def(const struct_member_t *member) +{ + if (member->type_def) + return member->type_def; + + return lookup_type_def(member->type); +} + +/** + * (As typed_var_assign, but assign a value to the member of object + * defined by member.) + **/ +int +struct_var_assign(void *object, const char *value, char **errmsg, + const struct_member_t *member) +{ + void *p = struct_get_mptr(object, member); + const var_type_def_t *def = get_type_def(member); + + return typed_var_assign_ex(p, value, errmsg, def); +} + +/** + * (As typed_var_free, but free and clear the member of object defined + * by member.) + **/ +void +struct_var_free(void *object, const struct_member_t *member) +{ + void *p = struct_get_mptr(object, member); + const var_type_def_t *def = get_type_def(member); + + typed_var_free_ex(p, def); +} + +/** + * (As typed_var_encode, but encode the member of object defined + * by member.) + **/ +char * +struct_var_encode(const void *object, const struct_member_t *member) +{ + const void *p = struct_get_ptr(object, member); + const var_type_def_t *def = get_type_def(member); + + return typed_var_encode_ex(p, def); +} + +/** + * (As typed_var_copy, but copy from src to dest the member + * defined by member.) + **/ +int +struct_var_copy(void *dest, const void *src, const struct_member_t *member) +{ + void *p_dest = struct_get_mptr(dest, member); + const void *p_src = struct_get_ptr(src, member); + const var_type_def_t *def = get_type_def(member); + + return typed_var_copy_ex(p_dest, p_src, def); +} + +/** + * (As typed_var_eq, but compare the members of a and b + * defined by member.) + **/ +bool +struct_var_eq(const void *a, const void *b, const struct_member_t *member) +{ + const void *p_a = struct_get_ptr(a, member); + const void *p_b = struct_get_ptr(b, member); + const var_type_def_t *def = get_type_def(member); + + return typed_var_eq_ex(p_a, p_b, def); +} + +/** + * (As typed_var_ok, but validate the member of object defined by + * member.) + **/ +bool +struct_var_ok(const void *object, const struct_member_t *member) +{ + const void *p = struct_get_ptr(object, member); + const var_type_def_t *def = get_type_def(member); + + return typed_var_ok_ex(p, def); +} + +/** + * (As typed_var_kvassign, but assign a value to the member of object + * defined by member.) + **/ +int +struct_var_kvassign(void *object, const struct config_line_t *line, + char **errmsg, + const struct_member_t *member) +{ + void *p = struct_get_mptr(object, member); + const var_type_def_t *def = get_type_def(member); + + return typed_var_kvassign_ex(p, line, errmsg, def); +} + +/** + * (As typed_var_kvencode, but encode the value of the member of object + * defined by member.) + **/ +struct config_line_t * +struct_var_kvencode(const void *object, const struct_member_t *member) +{ + const void *p = struct_get_ptr(object, member); + const var_type_def_t *def = get_type_def(member); + + return typed_var_kvencode_ex(member->name, p, def); +} diff --git a/src/lib/confmgt/structvar.h b/src/lib/confmgt/structvar.h new file mode 100644 index 0000000000..894098e509 --- /dev/null +++ b/src/lib/confmgt/structvar.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file structvar.h + * @brief Header for lib/confmgt/structvar.c + **/ + +#ifndef TOR_LIB_CONFMGT_STRUCTVAR_H +#define TOR_LIB_CONFMGT_STRUCTVAR_H + +struct struct_magic_decl_t; +struct struct_member_t; +struct config_line_t; + +#include + +void struct_set_magic(void *object, + const struct struct_magic_decl_t *decl); +void struct_check_magic(const void *object, + const struct struct_magic_decl_t *decl); + +void *struct_get_mptr(void *object, + const struct struct_member_t *member); +const void *struct_get_ptr(const void *object, + const struct struct_member_t *member); + +int struct_var_assign(void *object, const char *value, char **errmsg, + const struct struct_member_t *member); +void struct_var_free(void *object, + const struct struct_member_t *member); +char *struct_var_encode(const void *object, + const struct struct_member_t *member); +int struct_var_copy(void *dest, const void *src, + const struct struct_member_t *member); +bool struct_var_eq(const void *a, const void *b, + const struct struct_member_t *member); +bool struct_var_ok(const void *object, + const struct struct_member_t *member); + +int struct_var_kvassign(void *object, const struct config_line_t *line, + char **errmsg, + const struct struct_member_t *member); +struct config_line_t *struct_var_kvencode( + const void *object, + const struct struct_member_t *member); + +#endif /* !defined(TOR_LIB_CONFMGT_STRUCTVAR_H) */