The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
base.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or (at
6 * your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/**
19 * $Id: ea8823a6d19df4d7958df2b5074384de1508e379 $
20 * @file lib/redis/base.h
21 * @brief Common functions for interacting with Redis via hiredis
22 *
23 * @author Arran Cudbard-Bell
24 *
25 * @copyright 2015 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
26 * @copyright 2000,2006,2015 The FreeRADIUS server project
27 * @copyright 2011 TekSavvy Solutions (gabe@teksavvy.com)
28 */
29RCSIDH(redis_h, "$Id: ea8823a6d19df4d7958df2b5074384de1508e379 $")
30
31#include <freeradius-devel/server/base.h>
32#include <freeradius-devel/server/map.h>
33#include <freeradius-devel/server/module.h>
34#include <freeradius-devel/server/trunk.h>
35
36#include "config.h"
37
38#ifndef WITH_TLS
39# undef HAVE_REDIS_SSL
40#endif
41
42#ifdef HAVE_REDIS_SSL
43# include <freeradius-devel/tls/base.h>
44#endif
45
46//DIAG_OFF(extra-semi-stmt)
47#include <hiredis/hiredis.h>
48//DIAG_ON(extra-semi-stmt)
49
50#ifdef __cplusplus
51extern "C" {
52#endif
53
54#define MAX_REDIS_COMMAND_LEN 4096
55#define MAX_REDIS_ARGS 256
56
57#define REDIS_ERROR_MOVED_STR "MOVED"
58#define REDIS_ERROR_ASK_STR "ASK"
59#define REDIS_ERROR_TRY_AGAIN_STR "TRYAGAIN"
60#define REDIS_ERROR_NO_SCRIPT_STR "NOSCRIPT"
61#define REDIS_DEFAULT_PORT 6379
62
63#define REDIS_VERSION(_max, _min, _patch) (uint32_t) (_max << 24) | (_min << 16) | _patch
64
65typedef struct fr_redis_cluster_node_s fr_redis_cluster_node_t;
67
69extern size_t redis_reply_types_len;
71extern size_t redis_rcodes_len;
72
73/** Codes are ordered inversely by priority
74 *
75 * To simplify handling the return codes from pipelined commands,
76 * the lowest status code, and the reply which accompanies it should
77 * be returned to the redis cluster code.
78 */
79typedef enum : int8_t {
80 REDIS_RCODE_SUCCESS = 0, //!< Operation was successful.
81 REDIS_RCODE_ERROR = -1, //!< Unrecoverable library/server error.
82 REDIS_RCODE_TRY_AGAIN = -2, //!< Try the operation again.
83 REDIS_RCODE_RECONNECT = -3, //!< Transitory error, caller should retry the operation
84 //!< with a new connection.
85 REDIS_RCODE_ASK = -4, //!< Attempt operation on an alternative node.
86 REDIS_RCODE_MOVE = -5, //!< Attempt operation on an alternative node with remap.
87 REDIS_RCODE_NO_SCRIPT = -6, //!< Script doesn't exist.
89
90typedef enum : int8_t {
91 REDIS_ASYNC_RCODE_SUCCESS = 0, //!< Operation was successful.
92 REDIS_ASYNC_RCODE_ERROR = -1, //!< Unrecoverable error.
93 REDIS_ASYNC_RCODE_BOOTSTRAP = -2, //!< The caller should issue a request to bootstrap the cluster map.
94 REDIS_ASYNC_RCODE_GETMAP = -3, //!< The caller should issue a request to update the cluster map.
95
96 REDIS_ASYNC_RCODE_TRY_AGAIN = -4, //!< Try the operation again
97 REDIS_ASYNC_RCODE_ASK = -5, //!< Attempt operation on an alternative node.
98 REDIS_ASYNC_RCODE_MOVE = -6, //!< Attempt operation on an alternative node with remap.
99 REDIS_ASYNC_RCODE_NO_SCRIPT = -7, //!< Script doesn't exist.
100 REDIS_ASYNC_RCODE_FAIL = -8, //!< The command set trunk request has been failed.
102
103/** Connection handle, holding a redis context
104 */
105typedef struct {
106 redisContext *handle; //!< Hiredis context used when issuing commands.
107 fr_redis_cluster_node_t *node; //!< Node this connection is to.
109
119
120/** Configuration parameters for a redis connection
121 *
122 * @note should be passed as instance data to #module_rlm_connection_pool_init.
123 */
124typedef struct {
125 char const **hostname; //!< of Redis server.
126 uint16_t port; //!< of Redis daemon.
127 uint32_t database; //!< number on Redis server.
128 bool use_tls; //!< use TLS.
129 bool use_cluster_map;//!< use cluster map.
130
131 char const *username; //!< for acls.
132 char const *password; //!< to authenticate to Redis.
133
134 uint8_t max_nodes; //!< Maximum number of cluster nodes to connect to.
135 uint32_t max_redirects; //!< Maximum number of times we can be redirected.
136 uint32_t max_retries; //!< Maximum number of times we attempt a command
137 //!< when receiving successive -TRYAGAIN messages.
138 uint32_t max_alt; //!< Maximum alternative nodes to try.
139 fr_time_delta_t retry_delay; //!< How long to wait when we received a -TRYAGAIN
140 //!< message.
142
144
145 char const *log_prefix;
146
147 char const *module_name; //!< Module name for triggers.
148 char const *inst_name; //!< Instance name for triggers.
149
150 trunk_conf_t trunk_conf; //!< Configuration for trunk connections.
151#ifdef HAVE_REDIS_SSL
152 fr_tls_conf_t *tls; //!< Parsed from the `tls { ... }` subsection. NULL when
153 ///< the section is absent. An absent section is an error
154 ///< when `use_tls` is set.
155#endif
157
158/*
159 * `REDIS_TLS_CONFIG` comes first in `REDIS_COMMON_CONFIG`, so
160 * `REDIS_COMMON_CONFIG` never ends with a comma, whether or not
161 * `REDIS_TLS_CONFIG` expands to a row.
162 */
163#ifdef HAVE_REDIS_SSL
164# define REDIS_TLS_CONFIG \
165 { FR_CONF_SUBSECTION_ALLOC("tls", CONF_FLAG_OK_MISSING, fr_redis_conf_t, tls, fr_tls_client_config), \
166 .subcs_type = "fr_tls_conf_t" },
167#else
168# define REDIS_TLS_CONFIG
169#endif
170
171#define REDIS_COMMON_CONFIG \
172 REDIS_TLS_CONFIG \
173 { FR_CONF_OFFSET_FLAGS("server", CONF_FLAG_REQUIRED | CONF_FLAG_MULTI, fr_redis_conf_t, hostname) }, \
174 { FR_CONF_OFFSET("port", fr_redis_conf_t, port), .dflt = "6379" }, \
175 { FR_CONF_OFFSET("database", fr_redis_conf_t, database), .dflt = "0" }, \
176 { FR_CONF_OFFSET("use_tls", fr_redis_conf_t, use_tls), .dflt = "no" }, \
177 { FR_CONF_OFFSET("use_cluster_map", fr_redis_conf_t, use_cluster_map), .dflt = "yes" }, \
178 { FR_CONF_OFFSET("username", fr_redis_conf_t, username) }, \
179 { FR_CONF_OFFSET_FLAGS("password", CONF_FLAG_SECRET, fr_redis_conf_t, password) }, \
180 { FR_CONF_OFFSET("max_nodes", fr_redis_conf_t, max_nodes), .dflt = "20" }, \
181 { FR_CONF_OFFSET("max_alt", fr_redis_conf_t, max_alt), .dflt = "3" }, \
182 { FR_CONF_OFFSET("max_redirects", fr_redis_conf_t, max_redirects), .dflt = "2" }, \
183 { FR_CONF_OFFSET_SUBSECTION("pool", 0, fr_redis_conf_t, trunk_conf, trunk_config) }
184
185void fr_redis_version_print(void);
186
187int redis_dict_init(void);
188
189/*
190 * Command and resulting parsing
191 */
192void fr_redis_reply_print(fr_log_lvl_t lvl, redisReply *reply, request_t *request, int idx,
193 fr_redis_rcode_t status);
194
195int fr_redis_reply_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, redisReply *reply,
196 fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
197 bool box_error, bool shallow) CC_HINT(nonnull(2,3));
198
199int fr_redis_reply_to_map(TALLOC_CTX *ctx, map_list_t *out,
200 request_t *request, redisReply *key, redisReply *op, redisReply *value);
201
202int fr_redis_tuple_from_map(TALLOC_CTX *pool, char const *out[], size_t out_len[], map_t *map);
203
204int fr_redis_parse_version(char *out, size_t out_len, redisReply *reply);
205
206uint32_t fr_redis_version_num(char const *version);
207
208#ifdef __cplusplus
209}
210#endif
static uint8_t request[4]
static uint8_t reply[4]
#define RCSIDH(h, id)
Definition build.h:604
Thread local state for a cluster.
Test enumeration values.
Definition dict_test.h:92
fr_log_lvl_t
Definition log.h:64
unsigned short uint16_t
fr_type_t
unsigned int uint32_t
unsigned char uint8_t
void fr_redis_reply_print(fr_log_lvl_t lvl, redisReply *reply, request_t *request, int idx, fr_redis_rcode_t status)
Print the response data in a useful treelike form.
Definition redis.c:153
int fr_redis_reply_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, redisReply *reply, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, bool box_error, bool shallow))
Convert a string or integer type to fr_value_box_t of specified type.
Definition redis.c:222
uint8_t max_nodes
Maximum number of cluster nodes to connect to.
Definition base.h:134
fr_time_delta_t reconnection_delay
Definition base.h:143
fr_table_num_sorted_t const redis_rcodes[]
Definition redis.c:41
bool use_cluster_map
use cluster map.
Definition base.h:129
redisContext * handle
Hiredis context used when issuing commands.
Definition base.h:106
char const * username
for acls.
Definition base.h:131
fr_redis_rcode_t
Codes are ordered inversely by priority.
Definition base.h:79
@ REDIS_RCODE_RECONNECT
Transitory error, caller should retry the operation with a new connection.
Definition base.h:83
@ REDIS_RCODE_SUCCESS
Operation was successful.
Definition base.h:80
@ REDIS_RCODE_MOVE
Attempt operation on an alternative node with remap.
Definition base.h:86
@ REDIS_RCODE_TRY_AGAIN
Try the operation again.
Definition base.h:82
@ REDIS_RCODE_NO_SCRIPT
Script doesn't exist.
Definition base.h:87
@ REDIS_RCODE_ASK
Attempt operation on an alternative node.
Definition base.h:85
@ REDIS_RCODE_ERROR
Unrecoverable library/server error.
Definition base.h:81
int redis_dict_init(void)
Load the Redis dictionaries.
Definition redis.c:136
uint32_t database
number on Redis server.
Definition base.h:127
char const * inst_name
Instance name for triggers.
Definition base.h:148
trunk_conf_t trunk_conf
Configuration for trunk connections.
Definition base.h:150
fr_time_delta_t connection_timeout
Definition base.h:141
bool use_tls
use TLS.
Definition base.h:128
int fr_redis_tuple_from_map(TALLOC_CTX *pool, char const *out[], size_t out_len[], map_t *map)
Add a single map pair to an existing command string as three elements.
Definition redis.c:474
fr_redis_cluster_node_t * node
Node this connection is to.
Definition base.h:107
uint16_t port
of Redis daemon.
Definition base.h:126
size_t redis_reply_types_len
Definition redis.c:39
uint32_t max_redirects
Maximum number of times we can be redirected.
Definition base.h:135
void fr_redis_version_print(void)
Print the version of libhiredis the server was built against.
Definition redis.c:107
uint32_t fr_redis_version_num(char const *version)
Convert version string into a 32bit unsigned integer for comparisons.
Definition redis.c:569
char const * module_name
Module name for triggers.
Definition base.h:147
fr_table_num_sorted_t const redis_reply_types[]
Definition redis.c:31
size_t redis_rcodes_len
Definition redis.c:49
fr_time_delta_t retry_delay
How long to wait when we received a -TRYAGAIN message.
Definition base.h:139
char const * log_prefix
Definition base.h:145
char const ** hostname
of Redis server.
Definition base.h:125
int fr_redis_parse_version(char *out, size_t out_len, redisReply *reply)
Parse the reply from the Redis command INFO SERVER to extract the version.
Definition redis.c:535
char const * password
to authenticate to Redis.
Definition base.h:132
fr_redis_packet_code_t
Definition base.h:110
@ FR_REDIS_CLUSTER_MAP_BOOTSTRAP
Definition base.h:112
@ FR_REDIS_CODE_MAX
Definition base.h:116
@ FR_REDIS_CLUSTER_MAP_GET
Definition base.h:113
@ FR_REDIS_INVALID
Definition base.h:111
@ FR_REDIS_DO_NOT_RESPOND
Definition base.h:117
@ FR_REDIS_CLUSTER_MAP_UPDATE
Definition base.h:114
@ FR_REDIS_CLUSTER_MAP_FAIL
Definition base.h:115
fr_redis_async_rcode_t
Definition base.h:90
@ REDIS_ASYNC_RCODE_BOOTSTRAP
The caller should issue a request to bootstrap the cluster map.
Definition base.h:93
@ REDIS_ASYNC_RCODE_MOVE
Attempt operation on an alternative node with remap.
Definition base.h:98
@ REDIS_ASYNC_RCODE_ERROR
Unrecoverable error.
Definition base.h:92
@ REDIS_ASYNC_RCODE_GETMAP
The caller should issue a request to update the cluster map.
Definition base.h:94
@ REDIS_ASYNC_RCODE_ASK
Attempt operation on an alternative node.
Definition base.h:97
@ REDIS_ASYNC_RCODE_FAIL
The command set trunk request has been failed.
Definition base.h:100
@ REDIS_ASYNC_RCODE_TRY_AGAIN
Try the operation again.
Definition base.h:96
@ REDIS_ASYNC_RCODE_NO_SCRIPT
Script doesn't exist.
Definition base.h:99
@ REDIS_ASYNC_RCODE_SUCCESS
Operation was successful.
Definition base.h:91
uint32_t max_alt
Maximum alternative nodes to try.
Definition base.h:138
struct fr_redis_cluster_node_s fr_redis_cluster_node_t
Definition base.h:65
uint32_t max_retries
Maximum number of times we attempt a command when receiving successive -TRYAGAIN messages.
Definition base.h:136
int fr_redis_reply_to_map(TALLOC_CTX *ctx, map_list_t *out, request_t *request, redisReply *key, redisReply *op, redisReply *value)
Convert a pair of redis reply objects to a map.
Definition redis.c:381
Configuration parameters for a redis connection.
Definition base.h:124
Connection handle, holding a redis context.
Definition base.h:105
Value pair map.
Definition map.h:77
An element in a lexicographically sorted array of name to num mappings.
Definition table.h:49
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
Common configuration parameters for a trunk.
Definition trunk.h:234
static fr_sbuff_err_t char ** out
Definition value.h:1061
int nonnull(2, 5))