]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add functions to store/restore child request and session-state contents in a parent...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 Apr 2019 00:26:33 +0000 (20:26 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 Apr 2019 00:26:48 +0000 (20:26 -0400)
src/lib/server/request.c
src/lib/server/request.h
src/lib/server/state.c
src/lib/server/state.h

index 8c71defba196f4f26a88edee109c6c8ec4965097..43443915f096edd44c55330a4a5dc01f8b24f9d2 100644 (file)
@@ -545,6 +545,26 @@ int request_data_by_persistance(fr_dlist_head_t *out, REQUEST *request, bool per
        return count;
 }
 
+/** Return how many request data entries exist of a given persistence
+ *
+ * @param[in] request  to check in.
+ * @param[in] persist  Whether to count persistable or non-persistable data.
+ * @return number of request_data_t that exist in persistable or non-persistable form
+ */
+int request_data_by_persistance_count(REQUEST *request, bool persist)
+{
+       int             count = 0;
+       request_data_t  *rd = NULL;
+
+       while ((rd = fr_dlist_next(&request->data, rd))) {
+               if (rd->persist != persist) continue;
+
+               count++;
+       }
+
+       return count;
+}
+
 /** Add request data back to a request
  *
  * @note May add multiple entries (if they're linked).
@@ -558,6 +578,75 @@ void request_data_restore(REQUEST *request, fr_dlist_head_t *in)
        fr_dlist_move(&request->data, in);
 }
 
+/** Free any subrequest request data if the dlist head is freed
+ *
+ */
+static int _free_subrequest_data(fr_dlist_head_t *head)
+{
+       request_data_t *rd = NULL, *prev;
+
+       while ((rd = fr_dlist_next(head, rd))) {
+               prev = fr_dlist_remove(head, rd);
+               talloc_free(rd);
+               rd = prev;
+       }
+
+       return 0;
+}
+
+/** Store persistable data from a subrequest in its parent
+ *
+ * @param[in] request          The child request to retrieve state from.
+ * @param[in] unique_ptr       A parent may have multiple subrequests spawned
+ *                             by different modules.  This identifies the module
+ *                             or other facility that spawned the subrequest.
+ * @param[in] unique_int       Further identification.
+ */
+void request_data_store_in_parent(REQUEST *request, void *unique_ptr, int unique_int)
+{
+       fr_dlist_head_t *head;
+
+       if (request_data_by_persistance_count(request, true) == 0) return;
+
+       MEM(head = talloc_zero(request->parent->state_ctx, fr_dlist_head_t));
+       fr_dlist_talloc_init(head, request_data_t, list);
+       talloc_set_destructor(head, _free_subrequest_data);
+
+       /*
+        *      Pull everything out of the child,
+        *      add it to our temporary list head...
+        */
+       request_data_by_persistance(head, request, true);
+
+       /*
+        *      ...add that to the parent request under
+        *      the specified unique identifiers.
+        */
+       request_data_add(request->parent, unique_ptr, unique_int, head, true, false, true);
+}
+
+/** Restore subrequest data from a parent request
+ *
+ * @param[in] request          The child request to restore state to.
+ * @param[in] unique_ptr       A parent may have multiple subrequests spawned
+ *                             by different modules.  This identifies the module
+ *                             or other facility that spawned the subrequest.
+ * @param[in] unique_int       Further identification.
+ */
+void request_data_restore_to_child(REQUEST *request, void *unique_ptr, int unique_int)
+{
+       fr_dlist_head_t *head;
+
+       rad_assert(!request->state_ctx);
+       request->state_ctx = request->parent->state_ctx;        /* Use top level state ctx */
+
+       head = request_data_get(request->parent, unique_ptr, unique_int);
+       if (!head) return;
+
+       request_data_restore(request, head);
+       talloc_free(head);
+}
+
 #ifdef WITH_VERIFY_PTR
 /*
  *     Verify a packet.
index df7a7c3a26a343ac623756f3d35a76131fd27a13..d858394ca34cf9ab45cc3055b651b0900463afe7 100644 (file)
@@ -207,8 +207,14 @@ void               *request_data_reference(REQUEST *request, void const *unique_ptr, int uniq
 
 int            request_data_by_persistance(fr_dlist_head_t *out, REQUEST *request, bool persist);
 
+int            request_data_by_persistance_count(REQUEST *request, bool persist);
+
 void           request_data_restore(REQUEST *request, fr_dlist_head_t *in);
 
+void           request_data_store_in_parent(REQUEST *request, void *unique_ptr, int unique_int);
+
+void           request_data_restore_to_child(REQUEST *request, void *unique_ptr, int unique_int);
+
 #ifdef WITH_VERIFY_PTR
 void           request_verify(char const *file, int line, REQUEST const *request);     /* only for special debug builds */
 
index 95f9f7f4c69eb70158ec27506a7e11a8d4617f36..67448cf08754634a504ea559ce6efbc898646bd6 100644 (file)
@@ -107,7 +107,7 @@ typedef struct {
                                                                //!< tied to the lifetime of the request progression.
        VALUE_PAIR              *vps;                           //!< session-state VALUE_PAIRs, parented by ctx.
 
-       fr_dlist_head_t         data;                           //!< Persistable request data, also parented ctx.
+       fr_dlist_head_t         data;                           //!< Persistable request data, also parented by ctx.
 
        REQUEST                 *thawed;                        //!< The request that thawed this entry.
 } fr_state_entry_t;
@@ -716,6 +716,51 @@ int fr_request_to_state(fr_state_tree_t *state, REQUEST *request)
        return 0;
 }
 
+/** Store subrequest's session-state list and persistable request data in its parent
+ *
+ * @param[in] request          The child request to retrieve state from.
+ * @param[in] unique_ptr       A parent may have multiple subrequests spawned
+ *                             by different modules.  This identifies the module
+ *                             or other facility that spawned the subrequest.
+ * @param[in] unique_int       Further identification.
+ */
+void fr_state_store_in_parent(REQUEST *request, void *unique_ptr, int unique_int)
+{
+       rad_assert(request->parent);
+
+       RDEBUG3("Subrequest state - saved to %s", request->parent->name);
+
+       /*
+        *      Shove this into the child to make
+        *      it easier to store/restore the
+        *      whole lot...
+        */
+       request_data_add(request, (void *)fr_state_store_in_parent, 0, request->state, true, false, true);
+       request->state = NULL;
+
+       request_data_store_in_parent(request, unique_ptr, unique_int);
+}
+
+/** Restore subrequest data from a parent request
+ *
+ * @param[in] request          The child request to restore state to.
+ * @param[in] unique_ptr       A parent may have multiple subrequests spawned
+ *                             by different modules.  This identifies the module
+ *                             or other facility that spawned the subrequest.
+ * @param[in] unique_int       Further identification.
+ */
+void fr_state_restore_to_child(REQUEST *request, void *unique_ptr, int unique_int)
+{
+       RDEBUG3("Subrequest state - restored from %s", request->parent->name);
+
+       request_data_restore_to_child(request, unique_ptr, unique_int);
+
+       /*
+        *      Get the state vps back
+        */
+       request->state = request_data_get(request, (void *)fr_state_store_in_parent, 0);
+}
+
 /** Return number of entries created
  *
  */
index 4f76fab49a026d6fb0dadfff679d21c9da17e4e3..d2d5eaa9e1bc4cd8aa4fbe87187e69478fdbea16 100644 (file)
@@ -38,10 +38,13 @@ typedef struct fr_state_tree_t fr_state_tree_t;
 fr_state_tree_t *fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, bool thread_safe,
                                    uint32_t max_sessions, uint32_t timeout, uint8_t server_id);
 
-void fr_state_discard(fr_state_tree_t *state, REQUEST *request);
+void   fr_state_discard(fr_state_tree_t *state, REQUEST *request);
 
-void fr_state_to_request(fr_state_tree_t *state, REQUEST *request);
-int fr_request_to_state(fr_state_tree_t *state, REQUEST *request);
+void   fr_state_to_request(fr_state_tree_t *state, REQUEST *request);
+int    fr_request_to_state(fr_state_tree_t *state, REQUEST *request);
+
+void   fr_state_store_in_parent(REQUEST *request, void *unique_ptr, int unique_int);
+void   fr_state_restore_to_child(REQUEST *request, void *unique_ptr, int unique_int);
 
 /*
  *     Stats