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>
199 .offset = PROCESS_CONF_OFFSET(recv_solicit)
204 .offset = PROCESS_CONF_OFFSET(recv_request)
209 .offset = PROCESS_CONF_OFFSET(recv_confirm)
214 .offset = PROCESS_CONF_OFFSET(recv_renew)
219 .offset = PROCESS_CONF_OFFSET(recv_rebind)
224 .offset = PROCESS_CONF_OFFSET(recv_release)
229 .offset = PROCESS_CONF_OFFSET(recv_decline)
234 .offset = PROCESS_CONF_OFFSET(recv_reconfigure)
239 .offset = PROCESS_CONF_OFFSET(recv_information_request)
244 .offset = PROCESS_CONF_OFFSET(recv_relay_forward)
250 .offset = PROCESS_CONF_OFFSET(send_advertise)
260 .offset = PROCESS_CONF_OFFSET(send_relay_reply)
265 .offset = PROCESS_CONF_OFFSET(do_not_respond)
268 DYNAMIC_CLIENT_SECTIONS,
278 #ifdef WITH_IFINDEX_NAME_RESOLUTION
279 char if_name[IFNAMSIZ];
289 module = request->module;
290 request->module = NULL;
293 #ifdef WITH_IFINDEX_NAME_RESOLUTION
297 received ?
"Received" :
"Sending",
300 packet->
socket.inet.src_ipaddr.
af == AF_INET6 ?
"[" :
"",
302 packet->
socket.inet.src_ipaddr.
af == AF_INET6 ?
"]" :
"",
303 packet->
socket.inet.src_port,
304 packet->
socket.inet.dst_ipaddr.
af == AF_INET6 ?
"[" :
"",
306 packet->
socket.inet.dst_ipaddr.
af == AF_INET6 ?
"]" :
"",
307 packet->
socket.inet.dst_port
308 #ifdef WITH_IFINDEX_NAME_RESOLUTION
309 , packet->
socket.inet.ifindex ?
"via " :
"",
310 packet->
socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->
socket.inet.ifindex) :
"",
311 packet->
socket.inet.ifindex ?
" " :
""
315 if (received || request->parent) {
321 request->module = module;
327 static inline CC_HINT(always_inline)
334 if (!transaction_id) {
335 REDEBUG(
"Missing Transaction-ID");
340 REDEBUG(
"Invalid Transaction-ID, expected len %u, got len %zu",
358 REDEBUG(
"Error copying Client-ID");
374 REDEBUG(
"Error copying Server-ID");
378 if (expect_server_id) {
385 if (!expect_server_id) {
386 REDEBUG(
"Server-ID should not be present");
404 fr_process_state_t
const *state;
413 UPDATE_STATE_CS(packet);
416 cs, state->rcode, state->resume,
439 fr_process_state_t
const *state;
448 UPDATE_STATE_CS(packet);
451 cs, state->rcode, state->resume,
458 static inline CC_HINT(always_inline)
469 RWDEBUG(
"&reply.%pP does not match &request.%pP",
vp, *to_restore);
476 RPERROR(
"Failed adding %s", (*to_restore)->da->name);
485 static inline CC_HINT(always_inline)
501 static inline CC_HINT(always_inline)
506 bool moved_failure_message =
false;
508 if (!code || !*code)
return;
518 if ((vb->vb_uint16 == 0) && !
inst->status_code_on_success)
return;
530 if (
inst->move_failure_message_to_parent && request->parent && (request->parent->dict == request->dict)) {
542 moved_failure_message =
true;
550 if (
inst->send_failure_message && !moved_failure_message &&
562 fr_sbuff_init_talloc(
vp, &sbuff, &tctx, 1024, UINT16_MAX - 2);
569 failure_message->vp_length) < 0))
break;
570 }
while ((failure_message =
fr_pair_find_by_da(&request->request_pairs, failure_message,
585 fr_process_state_t
const *state;
609 return CALL_RESUME(send_generic);
616 return CALL_RESUME(send_generic);
622 static inline CC_HINT(always_inline)
625 fr_pair_t *hop_count, *link_address, *peer_address, *interface_id;
636 REDEBUG(
"Missing Link-Address");
642 REDEBUG(
"Missing Peer-Address");
666 fr_process_state_t
const *state;
673 UPDATE_STATE_CS(packet);
676 cs, state->rcode, state->resume,
687 fr_process_state_t
const *state;
702 return CALL_RESUME(send_generic);
710 return CALL_RESUME(send_generic);
718 fr_process_state_t
const *state;
725 request->component =
"dhcpv6";
726 request->module = NULL;
729 UPDATE_STATE(packet);
732 REDEBUG(
"Invalid packet type (%u)", request->packet->code);
739 return new_client(p_result, mctx, request);
742 return state->recv(p_result, mctx, request);
760 .recv = recv_for_any_server,
761 .resume = resume_recv_generic,
796 .recv = recv_for_this_server,
797 .resume = resume_recv_generic,
833 .recv = recv_for_any_server,
834 .resume = resume_recv_generic,
885 .recv = recv_for_this_server,
886 .resume = resume_recv_generic,
930 .recv = recv_for_any_server,
931 .resume = resume_recv_generic,
966 .recv = recv_for_any_server,
967 .resume = resume_recv_generic,
1002 .recv = recv_for_this_server,
1003 .resume = resume_recv_generic,
1041 .recv = recv_for_this_server,
1042 .resume = resume_recv_generic,
1080 .recv = recv_from_relay,
1081 .resume = resume_recv_generic,
1116 .send = send_generic,
1117 .resume = resume_send_to_client,
1156 .send = send_generic,
1157 .resume = resume_send_to_client,
1192 .send = send_generic,
1193 .resume = resume_send_to_relay,
1218 .send = send_generic,
1219 .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.
@ 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.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
fr_dict_attr_t const * attr_packet_type
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.
unlang_mod_actions_t const mod_actions_postauth
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
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_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 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
static int mod_instantiate(module_inst_ctx_t const *mctx)
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)
static int instantiate(module_inst_ctx_t const *mctx)
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 SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
#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
section_name_t const * section
Identifier for the section.
Processing sections which are allowed in this virtual server.