29 #define LOG_PREFIX "process_dhcpv6 - "
31 #include <freeradius-devel/io/application.h>
32 #include <freeradius-devel/server/protocol.h>
33 #include <freeradius-devel/server/pair.h>
34 #include <freeradius-devel/unlang/interpret.h>
35 #include <freeradius-devel/util/dict.h>
36 #include <freeradius-devel/util/debug.h>
37 #include <freeradius-devel/dhcpv6/dhcpv6.h>
38 #include <freeradius-devel/protocol/dhcpv6/freeradius.internal.h>
171 #define FR_DHCPV6_PROCESS_CODE_VALID(_x) (FR_DHCPV6_PACKET_CODE_VALID(_x) || (_x == FR_DHCPV6_DO_NOT_RESPOND))
173 #define PROCESS_PACKET_TYPE fr_dhcpv6_packet_code_t
174 #define PROCESS_CODE_MAX FR_DHCPV6_CODE_MAX
175 #define PROCESS_CODE_DO_NOT_RESPOND FR_DHCPV6_DO_NOT_RESPOND
176 #define PROCESS_PACKET_CODE_VALID FR_DHCPV6_PROCESS_CODE_VALID
177 #define PROCESS_INST process_dhcpv6_t
178 #define PROCESS_CODE_DYNAMIC_CLIENT FR_DHCPV6_REPLY
185 #define PROCESS_STATE_EXTRA_FIELDS fr_value_box_t const **status_codes[RLM_MODULE_NUMCODES];
186 #include <freeradius-devel/server/process.h>
200 .offset = PROCESS_CONF_OFFSET(recv_solicit)
206 .offset = PROCESS_CONF_OFFSET(recv_request)
212 .offset = PROCESS_CONF_OFFSET(recv_confirm)
218 .offset = PROCESS_CONF_OFFSET(recv_renew)
224 .offset = PROCESS_CONF_OFFSET(recv_rebind)
230 .offset = PROCESS_CONF_OFFSET(recv_release)
236 .offset = PROCESS_CONF_OFFSET(recv_decline)
240 .name2 =
"Reconfigure",
242 .offset = PROCESS_CONF_OFFSET(recv_reconfigure)
246 .name2 =
"Information-Request",
248 .offset = PROCESS_CONF_OFFSET(recv_information_request)
252 .name2 =
"Relay-Forward",
254 .offset = PROCESS_CONF_OFFSET(recv_relay_forward)
259 .name2 =
"Advertise",
261 .offset = PROCESS_CONF_OFFSET(send_advertise)
271 .name2 =
"Relay-Reply",
273 .offset = PROCESS_CONF_OFFSET(send_relay_reply)
277 .name2 =
"Do-Not-Respond",
279 .offset = PROCESS_CONF_OFFSET(do_not_respond)
282 DYNAMIC_CLIENT_SECTIONS,
292 #ifdef WITH_IFINDEX_NAME_RESOLUTION
293 char if_name[IFNAMSIZ];
303 module = request->module;
304 request->module = NULL;
307 #ifdef WITH_IFINDEX_NAME_RESOLUTION
311 received ?
"Received" :
"Sending",
314 packet->
socket.inet.src_ipaddr.
af == AF_INET6 ?
"[" :
"",
316 packet->
socket.inet.src_ipaddr.
af == AF_INET6 ?
"]" :
"",
317 packet->
socket.inet.src_port,
318 packet->
socket.inet.dst_ipaddr.
af == AF_INET6 ?
"[" :
"",
320 packet->
socket.inet.dst_ipaddr.
af == AF_INET6 ?
"]" :
"",
321 packet->
socket.inet.dst_port
322 #ifdef WITH_IFINDEX_NAME_RESOLUTION
323 , packet->
socket.inet.ifindex ?
"via " :
"",
324 packet->
socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->
socket.inet.ifindex) :
"",
325 packet->
socket.inet.ifindex ?
" " :
""
329 if (received || request->parent) {
335 request->module = module;
341 static inline CC_HINT(always_inline)
348 if (!transaction_id) {
349 REDEBUG(
"Missing Transaction-ID");
354 REDEBUG(
"Invalid Transaction-ID, expected len %u, got len %zu",
372 REDEBUG(
"Error copying Client-ID");
388 REDEBUG(
"Error copying Server-ID");
392 if (expect_server_id) {
399 if (!expect_server_id) {
400 REDEBUG(
"Server-ID should not be present");
418 fr_process_state_t
const *state;
427 UPDATE_STATE_CS(packet);
430 cs, state->rcode, state->resume,
453 fr_process_state_t
const *state;
462 UPDATE_STATE_CS(packet);
465 cs, state->rcode, state->resume,
472 static inline CC_HINT(always_inline)
483 RWDEBUG(
"&reply.%pP does not match &request.%pP",
vp, *to_restore);
490 RPERROR(
"Failed adding %s", (*to_restore)->da->name);
499 static inline CC_HINT(always_inline)
515 static inline CC_HINT(always_inline)
520 bool moved_failure_message =
false;
522 if (!code || !*code)
return;
532 if ((vb->vb_uint16 == 0) && !
inst->status_code_on_success)
return;
544 if (
inst->move_failure_message_to_parent && request->parent && (request->parent->dict == request->dict)) {
556 moved_failure_message =
true;
564 if (
inst->send_failure_message && !moved_failure_message &&
576 fr_sbuff_init_talloc(
vp, &sbuff, &tctx, 1024, UINT16_MAX - 2);
583 failure_message->vp_length) < 0))
break;
584 }
while ((failure_message =
fr_pair_find_by_da(&request->request_pairs, failure_message,
599 fr_process_state_t
const *state;
623 return CALL_RESUME(send_generic);
630 return CALL_RESUME(send_generic);
636 static inline CC_HINT(always_inline)
639 fr_pair_t *hop_count, *link_address, *peer_address, *interface_id;
650 REDEBUG(
"Missing Link-Address");
656 REDEBUG(
"Missing Peer-Address");
680 fr_process_state_t
const *state;
687 UPDATE_STATE_CS(packet);
690 cs, state->rcode, state->resume,
701 fr_process_state_t
const *state;
716 return CALL_RESUME(send_generic);
724 return CALL_RESUME(send_generic);
732 fr_process_state_t
const *state;
739 request->component =
"dhcpv6";
740 request->module = NULL;
743 UPDATE_STATE(packet);
746 REDEBUG(
"Invalid packet type (%u)", request->packet->code);
753 return new_client(p_result, mctx, request);
756 return state->recv(p_result, mctx, request);
774 .recv = recv_for_any_server,
775 .resume = resume_recv_generic,
810 .recv = recv_for_this_server,
811 .resume = resume_recv_generic,
847 .recv = recv_for_any_server,
848 .resume = resume_recv_generic,
899 .recv = recv_for_this_server,
900 .resume = resume_recv_generic,
944 .recv = recv_for_any_server,
945 .resume = resume_recv_generic,
980 .recv = recv_for_any_server,
981 .resume = resume_recv_generic,
1016 .recv = recv_for_this_server,
1017 .resume = resume_recv_generic,
1055 .recv = recv_for_this_server,
1056 .resume = resume_recv_generic,
1094 .recv = recv_from_relay,
1095 .resume = resume_recv_generic,
1130 .send = send_generic,
1131 .resume = resume_send_to_client,
1170 .send = send_generic,
1171 .resume = resume_send_to_client,
1206 .send = send_generic,
1207 .resume = resume_send_to_relay,
1232 .send = send_generic,
1233 .resume = resume_send_generic,
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define CONF_PARSER_TERMINATOR
#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
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
@ MOD_POST_AUTH
7 methods index for postauth section.
@ FR_DHCPV6_DO_NOT_RESPOND
@ FR_DHCPV6_INFORMATION_REQUEST
@ FR_DHCPV6_RELAY_FORWARD
#define DHCPV6_TRANSACTION_ID_LEN
fr_value_box_t const ** out
Enumeration value.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
Specifies a value which must be present for the module to function.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
CONF_SECTION *_CONST conf
Module's instance configuration.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
fr_dict_t const * dict_freeradius
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.
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.
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.
@ L_DBG_LVL_1
Highest priority debug messages (-x).
@ L_DBG
Only displayed when debugging is enabled.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_OCTETS
Raw octets.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
int fr_pair_cmp(fr_pair_t const *a, fr_pair_t const *b)
Compare two pairs, using the operator from "a".
int fr_pair_value_bstrndup_shallow(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Assign a string to a "string" type value pair.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
int fr_pair_list_copy_by_ancestor(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_dict_attr_t const *parent_da)
Duplicate pairs in a list where the da is a descendant of parent_da.
int fr_pair_steal_append(TALLOC_CTX *list_ctx, fr_pair_list_t *list, fr_pair_t *vp)
Change a vp's talloc ctx and insert it into a new list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
CONF_SECTION * send_advertise
CONF_SECTION * recv_information_request
static fr_dict_attr_t const * attr_packet_type
static fr_dict_attr_t const * attr_hop_count
CONF_SECTION * send_reply
static fr_dict_attr_t const * attr_status_code_message
CONF_SECTION * recv_solicit
static fr_dict_attr_t const * attr_module_failure_message
static fr_dict_attr_t const * attr_status_code_value
static fr_dict_attr_t const * attr_relay_link_address
static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Main dispatch function.
bool move_failure_message_to_parent
If true, and a parent exists, and the parent is a DHCPv6 request, all module failure messages will ge...
CONF_SECTION * recv_request
static int restore_field_list(request_t *request, fr_pair_list_t *to_restore)
fr_dict_autoload_t process_dhcpv6_dict[]
fr_dict_enum_autoload_t process_dhcpv6_dict_enum[]
static fr_value_box_t const * enum_status_code_success
fr_pair_t * transaction_id
static void status_code_add(process_dhcpv6_t const *inst, request_t *request, fr_value_box_t const **code)
Add a status code if one doesn't already exist.
CONF_SECTION * server_cs
Our virtual server.
static int restore_field(request_t *request, fr_pair_t **to_restore)
Copy a reply pair back into the response.
CONF_SECTION * do_not_respond
static fr_value_box_t const * enum_status_code_no_binding
bool status_code_on_success
Controls whether we add a status-code option to outbound packets if the status code would be 0.
CONF_SECTION * recv_decline
static fr_dict_attr_t const * attr_interface_id
static fr_dict_attr_t const * attr_server_id
CONF_SECTION * recv_relay_forward
CONF_SECTION * deny_client
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static fr_value_box_t const * enum_status_code_unspec_fail
CONF_SECTION * recv_rebind
static const virtual_server_compile_t compile_list[]
static conf_parser_t dhcpv6_process_config[]
CONF_SECTION * recv_release
static fr_process_state_t const process_state[]
CONF_SECTION * recv_renew
static void dhcpv6_packet_debug(request_t *request, fr_packet_t const *packet, fr_pair_list_t const *list, bool received)
CONF_SECTION * new_client
fr_dict_attr_autoload_t process_dhcpv6_dict_attr[]
static process_dhcpv6_relay_fields_t * dhcpv6_relay_fields_store(request_t *request)
Record the original hop-count, link-address, peer-address etc...
CONF_SECTION * add_client
bool send_failure_message
If true, all instances of Module-Failure-Message in the request are concatenated and returned in the ...
CONF_SECTION * recv_reconfigure
static fr_dict_t const * dict_dhcpv6
static fr_dict_attr_t const * attr_transaction_id
static process_dhcpv6_client_fields_t * dhcpv6_client_fields_store(request_t *request, bool expect_server_id)
Keep a copy of header fields to prevent them being tampered with.
static fr_dict_attr_t const * attr_client_id
static fr_value_box_t const * enum_status_code_not_on_link
CONF_SECTION * recv_confirm
#define PROCESS_PACKET_CODE_VALID
process_dhcpv6_sections_t sections
Pointers to various config sections we need to execute.
CONF_SECTION * send_relay_reply
static fr_dict_attr_t const * attr_relay_peer_address
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
fr_process_module_t process_dhcpv6
Records fields from the original request so we have a known good copy.
Records fields from the original relay-request so we have a known good copy.
#define PROCESS_TRACE
Trace each state function as it's entered.
module_t common
Common fields for all loadable modules.
Common public symbol definition for all process modules.
char const * fr_dhcpv6_packet_names[FR_DHCPV6_CODE_MAX]
static void send_reply(int sockfd, fr_channel_data_t *reply)
#define RETURN_MODULE_INVALID
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
#define request_is_dynamic_client(_x)
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len)
Trim a talloced sbuff to the minimum length required to represent the contained string.
ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len)
Copy bytes into the sbuff up to the first \0.
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_used(_sbuff_or_marker)
#define fr_sbuff_in_strcpy_literal(_sbuff, _str)
Talloc sbuff extension structure.
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
unlang_action_t unlang_module_yield_to_section(rlm_rcode_t *p_result, request_t *request, CONF_SECTION *subcs, rlm_rcode_t default_rcode, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
#define talloc_get_type_abort_const
unsigned int code
Packet code (type).
fr_socket_t socket
This packet was received on.
int id
Packet ID (used to link requests/responses).
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
int af
AF_INET, AF_INET6, or AF_UNIX.
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
#define fr_box_ipaddr(_val)
#define COMPILE_TERMINATOR
char const * name
Name of the processing section, such as "recv" or "send".
Processing sections which are allowed in this virtual server.