The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
base.c
Go to the documentation of this file.
1 /*
2  * This program 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
5  * (at 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: 8947eee3063fef9c9ba85f85d68087aba05e02b5 $
19  * @file src/process/vmps/base.c
20  * @brief VMPS processing.
21  *
22  * @copyright 2018 The Freeradius server project.
23  * @copyright 2018 Alan DeKok (aland@deployingradius.com)
24  */
25 #include <freeradius-devel/io/application.h>
26 #include <freeradius-devel/server/protocol.h>
27 #include <freeradius-devel/util/dict.h>
28 #include <freeradius-devel/util/debug.h>
29 #include <freeradius-devel/vmps/vmps.h>
30 
31 #include <freeradius-devel/protocol/vmps/vmps.h>
32 
33 static fr_dict_t const *dict_vmps;
34 
37  { .out = &dict_vmps, .proto = "vmps" },
38  { NULL }
39 };
40 
42 
45  { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_vmps },
46  { NULL }
47 };
48 
49 typedef struct {
50  uint64_t nothing; // so that the next field isn't at offset 0
51 
58 
59 typedef struct {
62 
63 #define PROCESS_PACKET_TYPE fr_vmps_packet_code_t
64 #define PROCESS_CODE_MAX FR_VMPS_CODE_MAX
65 #define PROCESS_CODE_DO_NOT_RESPOND FR_VMPS_DO_NOT_RESPOND
66 #define PROCESS_PACKET_CODE_VALID FR_VMPS_PACKET_CODE_VALID
67 #define PROCESS_INST process_vmps_t
68 #include <freeradius-devel/server/process.h>
69 
70 static fr_process_state_t const process_state[] = {
71  [FR_PACKET_TYPE_VALUE_JOIN_REQUEST] = {
72  .packet_type = {
73  [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_JOIN_RESPONSE,
74  [RLM_MODULE_NOOP] = FR_PACKET_TYPE_VALUE_JOIN_RESPONSE,
75  [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_JOIN_RESPONSE,
76 
77  [RLM_MODULE_REJECT] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
78  [RLM_MODULE_FAIL] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
79  [RLM_MODULE_INVALID] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
80  [RLM_MODULE_DISALLOW] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
81  [RLM_MODULE_NOTFOUND] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
82  },
83  .rcode = RLM_MODULE_NOOP,
84  .recv = recv_generic,
85  .resume = resume_recv_generic,
86  .section_offset = PROCESS_CONF_OFFSET(join_request),
87  },
88  [FR_PACKET_TYPE_VALUE_JOIN_RESPONSE] = {
89  .packet_type = {
90  [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_JOIN_RESPONSE,
91  [RLM_MODULE_NOOP] = FR_PACKET_TYPE_VALUE_JOIN_RESPONSE,
92  [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_JOIN_RESPONSE,
93 
94  [RLM_MODULE_REJECT] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
95  [RLM_MODULE_FAIL] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
96  [RLM_MODULE_INVALID] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
97  [RLM_MODULE_DISALLOW] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
98  [RLM_MODULE_NOTFOUND] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
99  },
100  .rcode = RLM_MODULE_NOOP,
101  .send = send_generic,
102  .resume = resume_send_generic,
103  .section_offset = PROCESS_CONF_OFFSET(join_response),
104  },
105 
106  [FR_PACKET_TYPE_VALUE_RECONFIRM_REQUEST] = {
107  .packet_type = {
108  [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_RECONFIRM_RESPONSE,
109  [RLM_MODULE_NOOP] = FR_PACKET_TYPE_VALUE_RECONFIRM_RESPONSE,
110  [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_RECONFIRM_RESPONSE,
111 
112  [RLM_MODULE_REJECT] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
113  [RLM_MODULE_FAIL] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
114  [RLM_MODULE_INVALID] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
115  [RLM_MODULE_DISALLOW] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
116  [RLM_MODULE_NOTFOUND] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
117  },
118  .rcode = RLM_MODULE_NOOP,
119  .recv = recv_generic,
120  .resume = resume_recv_generic,
121  .section_offset = PROCESS_CONF_OFFSET(reconfirm_request),
122  },
123  [FR_PACKET_TYPE_VALUE_RECONFIRM_RESPONSE] = {
124  .packet_type = {
125  [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_RECONFIRM_RESPONSE,
126  [RLM_MODULE_NOOP] = FR_PACKET_TYPE_VALUE_RECONFIRM_RESPONSE,
127  [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_RECONFIRM_RESPONSE,
128 
129  [RLM_MODULE_REJECT] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
130  [RLM_MODULE_FAIL] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
131  [RLM_MODULE_INVALID] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
132  [RLM_MODULE_DISALLOW] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
133  [RLM_MODULE_NOTFOUND] = FR_PACKET_TYPE_VALUE_DO_NOT_RESPOND,
134  },
135  .rcode = RLM_MODULE_NOOP,
136  .send = send_generic,
137  .resume = resume_send_generic,
138  .section_offset = PROCESS_CONF_OFFSET(reconfirm_response),
139  },
140 
141  [ FR_VMPS_DO_NOT_RESPOND ] = {
142  .packet_type = {
147 
153  },
154  .rcode = RLM_MODULE_NOOP,
155  .send = send_generic,
156  .resume = resume_send_generic,
157  .section_offset = PROCESS_CONF_OFFSET(do_not_respond),
158  },
159 };
160 
161 
162 /*
163  * Debug the packet if requested.
164  */
165 static void vmps_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
166 {
167 #ifdef WITH_IFINDEX_NAME_RESOLUTION
168  char if_name[IFNAMSIZ];
169 #endif
170 
171  if (!packet) return;
172  if (!RDEBUG_ENABLED) return;
173 
174  log_request(L_DBG, L_DBG_LVL_1, request, __FILE__, __LINE__, "%s %s XID %08x from %s%pV%s:%i to %s%pV%s:%i "
175 #ifdef WITH_IFINDEX_NAME_RESOLUTION
176  "%s%s%s"
177 #endif
178  "",
179  received ? "Received" : "Sending",
180  fr_vmps_packet_names[packet->code],
181  packet->id,
182  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
183  fr_box_ipaddr(packet->socket.inet.src_ipaddr),
184  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
185  packet->socket.inet.src_port,
186  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
187  fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
188  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
189  packet->socket.inet.dst_port
190 #ifdef WITH_IFINDEX_NAME_RESOLUTION
191  , packet->socket.inet.ifindex ? "via " : "",
192  packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
193  packet->socket.inet.ifindex ? " " : ""
194 #endif
195  );
196 
197  if (received || request->parent) {
198  log_request_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
199  } else {
200  log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, list, NULL);
201  }
202 }
203 
204 static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
205 {
206  fr_process_state_t const *state;
207 
209 
211  fr_assert(PROCESS_PACKET_CODE_VALID(request->packet->code));
212 
213  request->component = "vmps";
214  request->module = NULL;
215  fr_assert(request->dict == dict_vmps);
216 
217  UPDATE_STATE(packet);
218 
219  if (!state->recv) {
220  REDEBUG("Invalid packet type (%u)", request->packet->code);
222  }
223 
224  vmps_packet_debug(request, request->packet, &request->request_pairs, true);
225 
226  return state->recv(p_result, mctx, request);
227 }
228 
230  {
231  .section = SECTION_NAME("recv", "Join-Request"),
232  .actions = &mod_actions_authorize,
233  .offset = PROCESS_CONF_OFFSET(join_request),
234  },
235  {
236  .section = SECTION_NAME("send", "Join-Response"),
237  .actions = &mod_actions_postauth,
238  .offset = PROCESS_CONF_OFFSET(join_response),
239  },
240  {
241  .section = SECTION_NAME("recv", "Reconfirm-Request"),
242  .actions = &mod_actions_authorize,
243  .offset = PROCESS_CONF_OFFSET(reconfirm_request),
244  },
245  {
246  .section = SECTION_NAME("send", "Reconfirm-Response"),
247  .actions = &mod_actions_postauth,
248  .offset = PROCESS_CONF_OFFSET(reconfirm_response),
249  },
250  {
251  .section = SECTION_NAME("send", "Do-Not-Respond"),
252  .actions = &mod_actions_postauth,
253  .offset = PROCESS_CONF_OFFSET(do_not_respond),
254  },
255 
257 };
258 
259 
262  .common = {
263  .magic = MODULE_MAGIC_INIT,
264  .name = "vmps",
265  .inst_size = sizeof(process_vmps_t)
266  },
267  .process = mod_process,
268  .compile_list = compile_list,
269  .dict = &dict_vmps,
270 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:101
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:267
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:280
Specifies an attribute which must be present for the module to function.
Definition: dict.h:266
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:279
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
fr_dict_attr_t const * attr_packet_type
Definition: base.c:91
void log_request_proto_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a list of protocol fr_pair_ts.
Definition: log.c:854
void log_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt,...)
Marshal variadic log arguments into a va_list and pass to normal logging functions.
Definition: log.c:612
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
Definition: log.c:830
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition: log.h:70
@ L_DBG
Only displayed when debugging is enabled.
Definition: log.h:59
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
unlang_mod_actions_t const mod_actions_authorize
Definition: mod_action.c:44
unlang_mod_actions_t const mod_actions_postauth
Definition: mod_action.c:88
module_instance_t const * mi
Instance of the module being instantiated.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
CONF_SECTION * do_not_respond
Definition: base.c:56
CONF_SECTION * reconfirm_response
Definition: base.c:55
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: base.c:204
fr_dict_autoload_t process_vmps_dict[]
Definition: base.c:36
static void vmps_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
Definition: base.c:165
process_vmps_sections_t sections
Definition: base.c:60
fr_process_module_t process_vmps
Definition: base.c:261
static const virtual_server_compile_t compile_list[]
Definition: base.c:229
fr_dict_attr_autoload_t process_vmps_dict_attr[]
Definition: base.c:44
CONF_SECTION * reconfirm_request
Definition: base.c:54
static fr_process_state_t const process_state[]
Definition: base.c:70
CONF_SECTION * join_request
Definition: base.c:52
CONF_SECTION * join_response
Definition: base.c:53
#define PROCESS_PACKET_CODE_VALID
Definition: base.c:66
uint64_t nothing
Definition: base.c:50
static fr_dict_t const * dict_vmps
Definition: base.c:33
#define PROCESS_TRACE
Trace each state function as it's entered.
Definition: process.h:65
module_t common
Common fields for all loadable modules.
Definition: process.h:55
Common public symbol definition for all process modules.
Definition: process.h:54
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG_ENABLED()
Definition: radclient.h:49
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition: rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
Definition: rcode.h:46
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition: rcode.h:41
@ RLM_MODULE_NOTFOUND
User not found.
Definition: rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition: rcode.h:49
@ 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
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition: section.h:40
void * data
Module's instance data.
Definition: module.h:271
RETURN_MODULE_FAIL
fr_assert(0)
#define talloc_get_type_abort_const
Definition: talloc.h:282
unsigned int code
Packet code (type).
Definition: packet.h:61
fr_socket_t socket
This packet was received on.
Definition: packet.h:57
int id
Packet ID (used to link requests/responses).
Definition: packet.h:60
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition: socket.h:78
#define fr_box_ipaddr(_val)
Definition: value.h:294
#define COMPILE_TERMINATOR
section_name_t const * section
Identifier for the section.
Processing sections which are allowed in this virtual server.
char const * fr_vmps_packet_names[FR_VMPS_CODE_MAX]
Definition: vmps.c:75
@ FR_VMPS_DO_NOT_RESPOND
Definition: vmps.h:55