The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_sometimes.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 5db3c666482776066857f6a25939f3137f3dfac4 $
19  * @file rlm_sometimes.c
20  * @brief Switches between retuning different return codes.
21  *
22  * @copyright 2012 The FreeRADIUS server project
23  */
24 RCSID("$Id: 5db3c666482776066857f6a25939f3137f3dfac4 $")
25 
26 #include <freeradius-devel/server/base.h>
27 #include <freeradius-devel/server/module_rlm.h>
28 #include <freeradius-devel/radius/radius.h>
29 #include <freeradius-devel/util/debug.h>
30 
31 /*
32  * The instance data for rlm_sometimes is the list of fake values we are
33  * going to return.
34  */
35 typedef struct {
36  char const *rcode_str;
38  float percentage;
41 
42 static const conf_parser_t module_config[] = {
43  { FR_CONF_OFFSET("rcode", rlm_sometimes_t, rcode_str), .dflt = "fail" },
44  { FR_CONF_OFFSET_FLAGS("key", CONF_FLAG_ATTRIBUTE, rlm_sometimes_t, key), .dflt = "&User-Name", .quote = T_BARE_WORD },
45  { FR_CONF_OFFSET("percentage", rlm_sometimes_t, percentage), .dflt = "0" },
47 };
48 
49 static int mod_instantiate(module_inst_ctx_t const *mctx)
50 {
51  rlm_sometimes_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_sometimes_t);
52  CONF_SECTION *conf = mctx->mi->conf;
53 
54  /*
55  * Convert the rcode string to an int, and get rid of it
56  */
58  if (inst->rcode == RLM_MODULE_NOT_SET) {
59  cf_log_err(conf, "Unknown module return code '%s'", inst->rcode_str);
60  return -1;
61  }
62 
63  if ((inst->percentage < 0) || (inst->percentage > 100)) {
64  cf_log_err(conf, "Invalid value for 'percentage'. It must be 0..100 inclusive");
65  return -1;
66  }
67 
68  return 0;
69 }
70 
71 /*
72  * A lie! It always returns!
73  */
74 static unlang_action_t sometimes_return(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request,
75  fr_packet_t *packet, fr_packet_t *reply)
76 {
78  uint32_t hash;
79  fr_pair_t *vp;
80  float value;
81 
82  /*
83  * Set it to NOOP and the module will always do nothing
84  */
85  if (inst->rcode == RLM_MODULE_NOOP) RETURN_MODULE_RCODE(inst->rcode);
86 
87  /*
88  * Hash based on the given key. Usually User-Name.
89  */
90  if (tmpl_find_vp(&vp, request, inst->key) < 0) RETURN_MODULE_NOOP;
91 
92  switch (vp->vp_type) {
93  case FR_TYPE_OCTETS:
94  case FR_TYPE_STRING:
95  hash = fr_hash(vp->data.datum.ptr, vp->vp_length);
96  break;
97 
98  case FR_TYPE_STRUCTURAL:
100 
101  default:
102  hash = fr_hash(&vp->data.datum, fr_value_box_field_sizes[vp->vp_type]);
103  break;
104  }
105 
106  hash &= 0xffff; /* all we need are 2^16 bits of precision */
107  value = hash;
108  value /= (1 << 16);
109  value *= 100;
110 
111  if (value > inst->percentage) RETURN_MODULE_NOOP;
112 
113  /*
114  * If we're returning "handled", then set the packet
115  * code in the reply, so that the server responds.
116  *
117  * @todo - MULTI_PROTOCOL - make this protocol agnostic
118  */
119  if ((inst->rcode == RLM_MODULE_HANDLED) && reply) {
120  switch (packet->code) {
123  break;
124 
127  break;
128 
130  reply->code = FR_RADIUS_CODE_COA_ACK;
131  break;
132 
135  break;
136 
137  default:
138  break;
139  }
140  }
141 
142  RETURN_MODULE_RCODE(inst->rcode);
143 }
144 
145 static unlang_action_t CC_HINT(nonnull) mod_sometimes_packet(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
146 {
147  return sometimes_return(p_result, mctx, request, request->packet, request->reply);
148 }
149 
150 static unlang_action_t CC_HINT(nonnull) mod_sometimes_reply(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
151 {
152  return sometimes_return(p_result, mctx, request, request->reply, NULL);
153 }
154 
157  .common = {
158  .magic = MODULE_MAGIC_INIT,
159  .name = "sometimes",
160  .inst_size = sizeof(rlm_sometimes_t),
163  },
164  .method_group = {
165  .bindings = (module_method_binding_t[]){
166  { .section = SECTION_NAME("send", CF_IDENT_ANY), .method = mod_sometimes_reply },
167  { .section = SECTION_NAME(CF_IDENT_ANY, CF_IDENT_ANY), .method = mod_sometimes_packet },
169  }
170  }
171 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define RCSID(id)
Definition: build.h:481
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:627
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:268
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:256
@ CONF_FLAG_ATTRIBUTE
Value must resolve to attribute in dict (deprecated, use CONF_FLAG_TMPL).
Definition: cf_parse.h:407
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:564
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:101
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:289
#define CF_IDENT_ANY
Definition: cf_util.h:78
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition: defs.h:33
@ FR_RADIUS_CODE_DISCONNECT_REQUEST
RFC3575/RFC5176 - Disconnect-Request.
Definition: defs.h:46
@ FR_RADIUS_CODE_DISCONNECT_ACK
RFC3575/RFC5176 - Disconnect-Ack (positive)
Definition: defs.h:47
@ FR_RADIUS_CODE_COA_REQUEST
RFC3575/RFC5176 - CoA-Request.
Definition: defs.h:49
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition: defs.h:34
@ FR_RADIUS_CODE_ACCOUNTING_RESPONSE
RFC2866 - Accounting-Response.
Definition: defs.h:37
@ FR_RADIUS_CODE_COA_ACK
RFC3575/RFC5176 - CoA-Ack (positive)
Definition: defs.h:50
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
Definition: defs.h:36
Test enumeration values.
Definition: dict_test.h:92
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
uint32_t fr_hash(void const *data, size_t size)
Definition: hash.c:812
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned int uint32_t
Definition: merged_model.c:33
module_instance_t const * mi
Instance of the module being instantiated.
Definition: module_ctx.h:42
module_instance_t * mi
Instance of the module being instantiated.
Definition: module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:50
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:39
static const conf_parser_t config[]
Definition: base.c:183
static rs_t * conf
Definition: radsniff.c:53
fr_table_num_sorted_t const rcode_table[]
Definition: rcode.c:35
#define RETURN_MODULE_NOOP
Definition: rcode.h:62
#define RETURN_MODULE_RCODE(_rcode)
Definition: rcode.h:64
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_NOT_SET
Error resolving rcode (should not be returned by modules).
Definition: rcode.h:51
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition: rcode.h:48
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition: rcode.h:44
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:132
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1302
static unlang_action_t mod_sometimes_reply(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
rlm_rcode_t rcode
Definition: rlm_sometimes.c:37
char const * rcode_str
Definition: rlm_sometimes.c:36
static unlang_action_t sometimes_return(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request, fr_packet_t *packet, fr_packet_t *reply)
Definition: rlm_sometimes.c:74
module_rlm_t rlm_sometimes
static const conf_parser_t module_config[]
Definition: rlm_sometimes.c:42
static unlang_action_t mod_sometimes_packet(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_sometimes.c:49
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition: section.h:40
CONF_SECTION * conf
Module's instance configuration.
Definition: module.h:329
void * data
Module's instance data.
Definition: module.h:271
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition: module.h:151
Named methods exported by a module.
Definition: module.h:173
int tmpl_find_vp(fr_pair_t **out, request_t *request, tmpl_t const *vpt))
Returns the first VP matching a tmpl_t.
Definition: tmpl_eval.c:889
RETURN_MODULE_FAIL
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition: table.h:653
#define talloc_get_type_abort_const
Definition: talloc.h:282
@ T_BARE_WORD
Definition: token.h:120
unsigned int code
Packet code (type).
Definition: packet.h:61
#define FR_TYPE_STRUCTURAL
Definition: types.h:296
size_t const fr_value_box_field_sizes[]
How many bytes wide each of the value data fields are.
Definition: value.c:149
int nonnull(2, 5))