/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* @file type_defs.c
* @brief Definitions for various low-level configuration types.
*
* This module creates a number of var_type_def_t objects, to be used by
* typedvar.c in manipulating variables.
*
* The types here are common types that can be implemented with Tor's
* low-level functionality. To define new types, see var_type_def_st.h.
**/
#include "orconfig.h"
#include "lib/conf/conftypes.h"
#include "lib/conf/confdecl.h"
#include "lib/confmgt/typedvar.h"
#include "lib/confmgt/type_defs.h"
#include "lib/confmgt/unitparse.h"
#include "lib/cc/compat_compiler.h"
#include "lib/container/smartlist.h"
#include "lib/encoding/confline.h"
#include "lib/encoding/time_fmt.h"
#include "lib/log/escape.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/malloc/malloc.h"
#include "lib/string/parse_int.h"
#include "lib/string/printf.h"
#include "lib/confmgt/var_type_def_st.h"
#include <stddef.h>
#include <string.h>
#include <errno.h>
//////
// CONFIG_TYPE_STRING
// CONFIG_TYPE_FILENAME
//
// These two types are the same for now, but they have different names.
//
// Warning: For this type, the default value (NULL) and "" are considered
// different values. That is generally risky, and best avoided for other
// types in the future.
//////
static int
string_parse(void *target, const char *value, char **errmsg,
const void *params)
{
(void)params;
(void)errmsg;
char **p = (char**)target;
*p = tor_strdup(value);
return 0;
}
static char *
string_encode(const void *value, const void *params)
{
(void)params;
const char **p = (const char**)value;
return *p ? tor_strdup(*p) : NULL;
}
static void
string_clear(void *value, const void *params)
{
(void)params;
char **p = (char**)value;
tor_free(*p); // sets *p to NULL.
}
static const var_type_fns_t string_fns = {
.parse = string_parse,
.encode = string_encode,
.clear = string_clear,
};
/////
// CONFIG_TYPE_INT
// CONFIG_TYPE_POSINT
//
// These types are implemented as int, possibly with a restricted range.
/////
/**
* Parameters for parsing an integer type.
**/
typedef struct int_type_params_t {
int minval; /**< Lowest allowed value */
int maxval; /**< Highest allowed value */
} int_parse_params_t;
static const int_parse_params_t INT_PARSE_UNRESTRICTED = {
.minval = INT_MIN,
.maxval = INT_MAX,
};
static const int_parse_params_t INT_PARSE_POSINT = {
.minval = 0,
.maxval = INT_MAX,
};
static int
int_parse(void *target, const char *value, char **errmsg, const void *params)
{
const int_parse_params_t *pp;
if (params) {
pp = params;
} else {
pp = &INT_PARSE_UNRESTRICTED;
}
int *p = target;
int ok=0;
*p = (int)tor_parse_long(value, 10, pp->minval, pp->maxval, &ok, NULL);
if (!ok) {
tor_asprintf(errmsg, "Integer %s is malformed or out of bounds. "
"Allowed values are between %d and %d.",
value, pp->minval, pp->maxval);
return -1;
}
return 0;
}
static char *
int_encode(const void *value, const void *params)
{
(void)params;
int v = *(int*)value;
char *result;
tor_asprintf(&result, "%d", v);
return result;
}
static void
int_clear(void *value, const void *params)
{
(void)params;
*(int*)value = 0;
}
static bool
int_ok(const void *value, const void *params)
{
const int_parse_params_t *pp = params;
if (pp) {
int v = *(int*)value;
return pp->minval <= v && v <= pp->maxval;
} else {
return true;
}
}
static const var_type_fns_t int_fns = {
.parse = int_parse,
.encode = int_encode,
.clear = int_clear,
.ok = int_ok,
};
/////
// CONFIG_TYPE_UINT64
//
// This type is an unrestricted u64.
/////
static int
uint64_parse(void *target, const char *value, char **errmsg,
const void *params)
{
(void)params;
(void)errmsg;
uint64_t *p = target;
int ok=0;
*p = tor_parse_uint64(value, 10, 0, UINT64_MAX, &ok, NULL);