Commit 41261c3b authored by David Goulet's avatar David Goulet 🐼
Browse files

Merge branch 'tor-github/pr/1296'

parents 049705fc 478141e6
Loading
Loading
Loading
Loading

changes/ticket31625

0 → 100644
+4 −0
Original line number Diff line number Diff line
  o Code simplification and refactoring:
    - Replace our ad-hoc set of flags for configuration variables and
      configuration variable types with fine-grained orthogonal flags
      corresponding to the actual behavior we want. Closes ticket 31625.
+10 −3
Original line number Diff line number Diff line
@@ -267,10 +267,10 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);

#define VAR_NODUMP(varname,conftype,member,initvalue)             \
  CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member,       \
                   CVFLAG_NODUMP, initvalue)
                   CFLG_NODUMP, initvalue)
#define VAR_INVIS(varname,conftype,member,initvalue)              \
  CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member,       \
                   CVFLAG_NODUMP|CVFLAG_INVISIBLE, initvalue)
                   CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue)

#define V(member,conftype,initvalue)            \
  VAR(#member, conftype, member, initvalue)
@@ -2671,6 +2671,9 @@ list_torrc_options(void)
{
  smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
  SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
    /* Possibly this should check listable, rather than (or in addition to)
     * settable. See ticket 31654.
     */
    if (! config_var_is_settable(var)) {
      /* This variable cannot be set, or cannot be set by this name. */
      continue;
@@ -2685,6 +2688,8 @@ static void
list_deprecated_options(void)
{
  smartlist_t *deps = config_mgr_list_deprecated_vars(get_options_mgr());
  /* Possibly this should check whether the variables are listable,
   * but currently it does not.  See ticket 31654. */
  SMARTLIST_FOREACH(deps, const char *, name,
                    printf("%s\n", name));
  smartlist_free(deps);
@@ -8133,7 +8138,7 @@ getinfo_helper_config(control_connection_t *conn,
    smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
    SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
      /* don't tell controller about invisible options */
      if (config_var_is_invisible(var))
      if (! config_var_is_listable(var))
        continue;
      const char *type = struct_var_get_typename(&var->member);
      if (!type)
@@ -8147,6 +8152,8 @@ getinfo_helper_config(control_connection_t *conn,
  } else if (!strcmp(question, "config/defaults")) {
    smartlist_t *sl = smartlist_new();
    int dirauth_lines_seen = 0, fallback_lines_seen = 0;
    /* Possibly this should check whether the variables are listable,
     * but currently it does not.  See ticket 31654. */
    smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
    SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
      if (var->initvalue != NULL) {
+103 −21
Original line number Diff line number Diff line
@@ -511,32 +511,112 @@ config_count_options(const config_mgr_t *mgr)
  return smartlist_len(mgr->all_vars);
}

bool
config_var_is_cumulative(const config_var_t *var)
/**
 * Return true iff at least one bit from <b>flag</b> is set on <b>var</b>,
 * either in <b>var</b>'s flags, or on the flags of its type.
 **/
static bool
config_var_has_flag(const config_var_t *var, uint32_t flag)
{
  return struct_var_is_cumulative(&var->member);
  uint32_t have_flags = var->flags | struct_var_get_flags(&var->member);

  return (have_flags & flag) != 0;
}

/**
 * Return true if assigning a value to <b>var</b> replaces the previous
 * value.  Return false if assigning a value to <b>var</b> appends
 * to the previous value.
 **/
static bool
config_var_is_replaced_on_set(const config_var_t *var)
{
  return ! config_var_has_flag(var, CFLG_NOREPLACE);
}

/**
 * Return true iff <b>var</b> may be assigned by name (e.g., via the
 * CLI, the configuration files, or the controller API).
 **/
bool
config_var_is_settable(const config_var_t *var)
{
  if (var->flags & CVFLAG_OBSOLETE)
    return false;
  return struct_var_is_settable(&var->member);
  return ! config_var_has_flag(var, CFLG_NOSET);
}
bool
config_var_is_contained(const config_var_t *var)

/**
 * Return true iff the controller is allowed to fetch the value of
 * <b>var</b>.
 **/
static bool
config_var_is_gettable(const config_var_t *var)
{
  return struct_var_is_contained(&var->member);
  /* Arguably, invisible or obsolete options should not be gettable.  However,
   * they have been gettable for a long time, and making them ungettable could
   * have compatibility effects.  For now, let's leave them alone.
   */

  // return ! config_var_has_flag(var, CVFLAG_OBSOLETE|CFGLAGS_INVISIBLE);
  (void)var;
  return true;
}
bool
config_var_is_invisible(const config_var_t *var)

/**
 * Return true iff we need to check <b>var</b> for changes when we are
 * comparing config options for changes.
 *
 * A false result might mean that the variable is a derived variable, and that
 * comparing the variable it derives from compares this one too-- or it might
 * mean that there is no data to compare.
 **/
static bool
config_var_should_list_changes(const config_var_t *var)
{
  return (var->flags & CVFLAG_INVISIBLE) != 0;
  return ! config_var_has_flag(var, CFLG_NOCMP);
}

/**
 * Return true iff we need to copy the data for <b>var</b> when we are
 * copying a config option.
 *
 * A false option might mean that the variable is a derived variable, and that
 * copying the variable it derives from copies it-- or it might mean that
 * there is no data to copy.
 **/
static bool
config_var_needs_copy(const config_var_t *var)
{
  return ! config_var_has_flag(var, CFLG_NOCOPY);
}

/**
 * Return true iff variable <b>var</b> should appear on list of variable
 * names given to the controller or the CLI.
 *
 * (Note that this option is imperfectly obeyed. The
 * --list-torrc-options command looks at the "settable" flag, whereas
 * "GETINFO config/defaults" and "list_deprecated_*()" do not filter
 * their results. It would be good for consistency to try to converge
 * these behaviors in the future.)
 **/
bool
config_var_is_listable(const config_var_t *var)
{
  return ! config_var_has_flag(var, CFLG_NOLIST);
}

/**
 * Return true iff variable <b>var</b> should be written out when we
 * are writing our configuration to disk, to a controller, or via the
 * --dump-config command.
 *
 * This option may be set because a variable is hidden, or because it is
 * derived from another variable which will already be written out.
 **/
static bool
config_var_is_dumpable(const config_var_t *var)
{
  return (var->flags & CVFLAG_NODUMP) == 0;
  return ! config_var_has_flag(var, CFLG_NODUMP);
}

/*
@@ -650,7 +730,8 @@ config_assign_line(const config_mgr_t *mgr, void *options,
  if (!strlen(c->value)) {
    /* reset or clear it, then return */
    if (!clear_first) {
      if (config_var_is_cumulative(cvar) && c->command != CONFIG_LINE_CLEAR) {
      if (! config_var_is_replaced_on_set(cvar) &&
          c->command != CONFIG_LINE_CLEAR) {
        /* We got an empty linelist from the torrc or command line.
           As a special case, call this an error. Warn and ignore. */
        log_warn(LD_CONFIG,
@@ -671,7 +752,7 @@ config_assign_line(const config_mgr_t *mgr, void *options,
    // LCOV_EXCL_STOP
  }

  if (options_seen && ! config_var_is_cumulative(cvar)) {
  if (options_seen && config_var_is_replaced_on_set(cvar)) {
    /* We're tracking which options we've seen, and this option is not
     * supposed to occur more than once. */
    tor_assert(var_index >= 0);
@@ -750,6 +831,11 @@ config_get_assigned_option(const config_mgr_t *mgr, const void *options,
    log_warn(LD_CONFIG, "Unknown option '%s'.  Failing.", key);
    return NULL;
  }
  if (! config_var_is_gettable(var->cvar)) {
    log_warn(LD_CONFIG, "Option '%s' is obsolete or unfetchable. Failing.",
             key);
    return NULL;
  }
  const void *object = config_mgr_get_obj(mgr, options, var->object_idx);

  result = struct_var_kvencode(object, &var->cvar->member);
@@ -989,7 +1075,7 @@ config_get_changes(const config_mgr_t *mgr,
  config_line_t *result = NULL;
  config_line_t **next = &result;
  SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) {
    if (config_var_is_contained(mv->cvar)) {
    if (! config_var_should_list_changes(mv->cvar)) {
      /* something else will check this var, or it doesn't need checking */
      continue;
    }
@@ -1025,7 +1111,7 @@ config_dup(const config_mgr_t *mgr, const void *old)

  newopts = config_new(mgr);
  SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) {
    if (config_var_is_contained(mv->cvar)) {
    if (! config_var_needs_copy(mv->cvar)) {
      // Something else will copy this option, or it doesn't need copying.
      continue;
    }
@@ -1092,10 +1178,6 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
  elements = smartlist_new();
  SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) {
    int comment_option = 0;
    if (config_var_is_contained(mv->cvar)) {
      // Something else will dump this option, or it doesn't need dumping.
      continue;
    }
    /* Don't save 'hidden' control variables. */
    if (! config_var_is_dumpable(mv->cvar))
      continue;
+1 −4
Original line number Diff line number Diff line
@@ -189,11 +189,8 @@ const char *config_expand_abbrev(const config_mgr_t *mgr,
                                 int command_line, int warn_obsolete);
void warn_deprecated_option(const char *what, const char *why);

bool config_var_is_cumulative(const config_var_t *var);
bool config_var_is_settable(const config_var_t *var);
bool config_var_is_contained(const config_var_t *var);
bool config_var_is_invisible(const config_var_t *var);
bool config_var_is_dumpable(const config_var_t *var);
bool config_var_is_listable(const config_var_t *var);

/* Helper macros to compare an option across two configuration objects */
#define CFG_EQ_BOOL(a,b,opt) ((a)->opt == (b)->opt)
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@

#define CONFIG_VAR_OBSOLETE(varname)            \
  { .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE },        \
    .flags = CVFLAG_OBSOLETE                                            \
    .flags = CFLG_GROUP_OBSOLETE                                        \
  }

#endif /* !defined(TOR_LIB_CONF_CONFMACROS_H) */
Loading