]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
more rework to add request_ctx for packet BIOs
authorAlan T. DeKok <aland@freeradius.org>
Wed, 13 Mar 2024 21:15:57 +0000 (17:15 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 13 Mar 2024 21:15:57 +0000 (17:15 -0400)
so that we can not only encode a packet + pairs, but also associate
that with a larger request context

src/lib/bio/packet.h
src/lib/bio/retry.c
src/lib/bio/retry.h
src/protocols/radius/client.c
src/protocols/radius/client.h
src/protocols/radius/client_priv.h
src/protocols/radius/client_tcp.c
src/protocols/radius/client_udp.c
src/protocols/radius/id.c
src/protocols/radius/id.h

index 4692dc84b2ba3145e0d9225889087bcc7c53aa0a..ec0b537f87a2cf1a6957ffed2178349679d06250 100644 (file)
@@ -34,25 +34,27 @@ typedef struct fr_bio_packet_s fr_bio_packet_t;
 /** Read a packet and pairs from the network
  *
  * @param bio          the packet-based bio
- * @param packet_p     the output packet descriptor.  Contains raw protocol data (IDs, counts, etc.)
- * @param ctx          the talloc_ctx for the list
+ * @param request_ctx_p        the request context associated with the response
+ * @param packet_p     the response packet.  Contains raw protocol data (IDs, counts, etc.)
+ * @param out_ctx      talloc context for the list
  * @param out          the decoded pairs from the packet
  * @return
  *     - <0 on error
  *     - 0 for success (*packet_p may still be NULL tho)
  */
-typedef int (*fr_bio_packet_read_t)(fr_bio_packet_t *bio, fr_packet_t **packet_p, TALLOC_CTX *ctx, fr_pair_list_t *out);
+typedef int (*fr_bio_packet_read_t)(fr_bio_packet_t *bio, void **request_ctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out);
 
 /** Write a packet and pairs from the network
  *
  * @param bio          the packet-based bio
- * @param packet       the output packet descriptor.  Contains raw protocol data (IDs, counts, etc.)
+ * @param request_ctx  the request context
+ * @param packet       the request packet.  Contains raw protocol data (IDs, counts, etc.)
  * @param list         the pairs to encode in the packet
  * @return
  *     - <0 on error (EOF, fail, etc,)
  *     - 0 for success
  */
-typedef int (*fr_bio_packet_write_t)(fr_bio_packet_t *bio, fr_packet_t *packet, fr_pair_list_t *list);
+typedef int (*fr_bio_packet_write_t)(fr_bio_packet_t *bio, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list);
 
 /** Release an outgoing packet.
  *
@@ -74,12 +76,12 @@ struct fr_bio_packet_s {
 };
 
 
-static inline CC_HINT(nonnull) int fr_bio_packet_read(fr_bio_packet_t *bio, fr_packet_t **packet_p, TALLOC_CTX *ctx, fr_pair_list_t *out)
+static inline CC_HINT(nonnull) int fr_bio_packet_read(fr_bio_packet_t *bio, void **request_ctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out)
 {
-       return bio->read(bio, packet_p, ctx, out);
+       return bio->read(bio, request_ctx_p, packet_p, out_ctx, out);
 }
 
-static inline CC_HINT(nonnull) int fr_bio_packet_write(fr_bio_packet_t *bio, fr_packet_t *packet, fr_pair_list_t *list)
+static inline CC_HINT(nonnull) int fr_bio_packet_write(fr_bio_packet_t *bio, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
 {
-       return bio->write(bio, packet, list);
+       return bio->write(bio, request_ctx, packet, list);
 }
index 5c764506b6cdca0ee35b245bf14be4c0e7798f17..f939faf7ca229f6e1109c7e6d3834d974de6b6c6 100644 (file)
  */
 
 #include <freeradius-devel/bio/bio_priv.h>
-#include <freeradius-devel/bio/retry.h>
 #include <freeradius-devel/bio/null.h>
 #include <freeradius-devel/bio/buf.h>
 #include <freeradius-devel/util/rb.h>
 #include <freeradius-devel/util/dlist.h>
 
+#define _BIO_RETRY_PRIVATE
+#include <freeradius-devel/bio/retry.h>
+
 typedef struct fr_bio_retry_list_s     fr_bio_retry_list_t;
 typedef struct fr_bio_retry_s  fr_bio_retry_t;
 
@@ -38,6 +40,9 @@ typedef struct fr_bio_retry_s fr_bio_retry_t;
 FR_DLIST_TYPES(fr_bio_retry_list)
 
 struct fr_bio_retry_entry_s {
+       void            *uctx;
+       void            *packet_ctx;
+
        union {
                fr_rb_node_t    node;           //!< for the timers
                FR_DLIST_ENTRY(fr_bio_retry_list) entry; //!< for the free list
@@ -46,7 +51,6 @@ struct fr_bio_retry_entry_s {
        fr_bio_retry_t  *my;                    //!< so we can get to it from the event timer callback
        fr_retry_t      retry;                  //!< retry timers and counters
 
-       void            *packet_ctx;
        uint8_t const   *buffer;
        size_t          size;   
        size_t          partial;                //!< for partial writes :(
@@ -132,7 +136,7 @@ static void fr_bio_retry_release(fr_bio_retry_t *my, fr_bio_retry_entry_t *item,
                (void) fr_bio_retry_reset_timer(my);
        }
 
-       my->release((fr_bio_t *) my, item->packet_ctx, item->buffer, item->size, reason);
+       my->release((fr_bio_t *) my, item, reason);
 
 #ifndef NDEBUG
        item->buffer = NULL;
@@ -569,7 +573,8 @@ static int8_t _entry_cmp(void const *one, void const *two)
  *  @param item                the retry context from #fr_bio_retry_save_t
  *  @return
  *     - <0 error
- *     - 0 for success
+ *     - 0 - didn't cancel
+ *     - 1 - did cancel
  */
 int fr_bio_retry_entry_cancel(fr_bio_t *bio, fr_bio_retry_entry_t *item)
 {
@@ -582,12 +587,15 @@ int fr_bio_retry_entry_cancel(fr_bio_t *bio, fr_bio_retry_entry_t *item)
                item = fr_rb_last(&my->rb);
                if (!item) return 0;
 
-               if (!item->retry.replies) return -1; /* can't cancel it */
+               /*
+                *      This item hasn't had a response, we can't cancel it.
+                */
+               if (!item->retry.replies) return 0;
        }
 
        fr_assert(item->buffer != NULL);
 
-       if (item->cancelled) return 0;
+       if (item->cancelled) return 1;
 
        /*
         *      If we've written a partial packet, jump through a bunch of hoops to cache the partial packet
@@ -624,7 +632,7 @@ int fr_bio_retry_entry_cancel(fr_bio_t *bio, fr_bio_retry_entry_t *item)
        if (my->first == item) my->first = NULL;
 
        fr_bio_retry_release(my, item, item->have_reply ? FR_BIO_RETRY_DONE : FR_BIO_RETRY_CANCELLED);
-       return 0;
+       return 1;
 }
 
 /**  Set a per-packet retry config 
@@ -668,14 +676,11 @@ static int fr_bio_retry_destructor(fr_bio_retry_t *my)
        talloc_const_free(my->ev);
 
        /*
-        *      Cancel all outgoing packets.
+        *      Cancel all outgoing packets.  Don't bother updating the tree or the free list, as all of the
+        *      entries will be deleted when the memory is freed.
         */
        while ((item = fr_rb_iter_init_inorder(&iter, &my->rb)) != NULL) {
-               (void) fr_rb_remove_by_inline_node(&my->rb, &item->node);
-#ifndef NDEBUG
-               fr_bio_retry_list_insert_head(&my->free, item);
-#endif
-               my->release((fr_bio_t *) my, item->packet_ctx, item->buffer, item->size, FR_BIO_RETRY_CANCELLED);
+               my->release((fr_bio_t *) my, item, FR_BIO_RETRY_CANCELLED);
        }
 
        my->first = NULL;
index 888e0e3a8242c3c872428dadae154d057a091730..6e4ebfbc3a7809a8ff9807d02ec99a035d6489b4 100644 (file)
@@ -40,6 +40,13 @@ typedef struct {
 
 typedef struct fr_bio_retry_entry_s fr_bio_retry_entry_t;
 
+#ifndef _BIO_RETRY_PRIVATE
+struct  fr_bio_retry_entry_s {
+       void            *uctx;                  //!< user-writable context
+       void            *packet_ctx;            //!< packet_ctx from the write() call
+};
+#endif
+
 typedef enum {
        FR_BIO_RETRY_DONE = 0,
        FR_BIO_RETRY_NO_REPLY,
@@ -93,12 +100,10 @@ typedef bool (*fr_bio_retry_response_t)(fr_bio_t *bio, fr_bio_retry_entry_t **it
  *  The packet will be cancelled after this call returns.  The cancellation callback will NOT be run.
  *
  *  @param bio         the binary IO handler
- *  @param packet_ctx  per-packet context
- *  @param buffer      raw data for the packet
- *  @param size                size of the raw data
+ *  @param retry_ctx   the retry ctx to release
  *  @param reason      why this packet is being released
  */
-typedef void   (*fr_bio_retry_release_t)(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size, fr_bio_retry_release_reason_t reason);
+typedef void   (*fr_bio_retry_release_t)(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, fr_bio_retry_release_reason_t reason);
 
 fr_bio_t       *fr_bio_retry_alloc(TALLOC_CTX *ctx, size_t max_saved,
                                    fr_bio_retry_sent_t sent,
index 44ac6dbab85a2788278b696152ab581928298176..56192a26629567de5e21172572244739c8c68d7a 100644 (file)
@@ -98,10 +98,10 @@ fr_radius_client_fd_bio_t *fr_radius_client_fd_bio_alloc(TALLOC_CTX *ctx, size_t
        return my;
 }
 
-int fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, fr_packet_t *packet, fr_pair_list_t *list)
+int fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
 {
        ssize_t slen;
-       fr_radius_client_packet_ctx_t *ctx;
+       fr_radius_id_ctx_t *id_ctx;
 
        fr_assert(!packet->data);
 
@@ -114,18 +114,22 @@ int fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, fr_packet_t *pa
                return -1;
        }
 
-       if (fr_radius_code_id_pop(my->codes, packet) < 0) {
-               fr_strerror_const("All IDs are in use");
-               return -1;
-       }
+       id_ctx = fr_radius_code_id_pop(my->codes, packet);
+       if (!id_ctx) {
+               /*
+                *      Try to cancel the oldest one.
+                */
+               if (fr_bio_retry_entry_cancel(my->retry, NULL) < 1) {
+               all_ids_used:
+                       fr_strerror_const("All IDs are in use");
+                       return -1;
+               }
 
-       /*
-        *      Initialize our client retry data structure.
-        */
-       ctx = packet->uctx;
-       ctx->retry_ctx = NULL;
-       ctx->packet = packet;
-       ctx->reply = NULL;
+               id_ctx = fr_radius_code_id_pop(my->codes, packet);
+               if (!id_ctx) goto all_ids_used;
+       }
+       id_ctx->request_ctx = request_ctx;
+       fr_assert(id_ctx->packet == packet);
 
        /*
         *      Encode the packet.
@@ -138,13 +142,13 @@ int fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, fr_packet_t *pa
 
        if (fr_packet_sign(packet, NULL, (char const *) my->cfg.verify.secret) < 0) goto fail;
 
-       slen = fr_bio_write(my->common.bio, ctx, packet->data, packet->data_len);
+       slen = fr_bio_write(my->common.bio, &packet->socket, packet->data, packet->data_len);
        if (slen <= 0) goto fail;
 
        return 0;
 }
 
-#if 0
+#if 1
 static const fr_radius_packet_code_t allowed_replies[FR_RADIUS_CODE_MAX] = {
        [FR_RADIUS_CODE_ACCESS_ACCEPT]          = FR_RADIUS_CODE_ACCESS_REQUEST,
        [FR_RADIUS_CODE_ACCESS_CHALLENGE]       = FR_RADIUS_CODE_ACCESS_REQUEST,
@@ -161,28 +165,33 @@ static const fr_radius_packet_code_t allowed_replies[FR_RADIUS_CODE_MAX] = {
        [FR_RADIUS_CODE_PROTOCOL_ERROR]         = FR_RADIUS_CODE_PROTOCOL_ERROR,        /* Any */
 };
 
-static void radius_client_retry_sent(UNUSED fr_bio_t *bio, void *packet_ctx, UNUSED const void *buffer, UNUSED size_t size,
+static void radius_client_retry_sent(fr_bio_t *bio, void *packet_ctx, const void *buffer, UNUSED size_t size,
                                     fr_bio_retry_entry_t *retry_ctx)
 {
-       fr_radius_client_packet_ctx_t *ctx = packet_ctx;
+       fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_client_fd_bio_t);
+       fr_radius_id_ctx_t *id_ctx;
+       uint8_t const *data = buffer;
 
-       ctx->retry_ctx = retry_ctx;
+       id_ctx = fr_radius_code_id_find(my->codes, data[0], data[1]);
+       fr_assert(id_ctx != NULL);
+
+       id_ctx->packet = packet_ctx;
+       id_ctx->retry_ctx = retry_ctx;
+       retry_ctx->uctx = id_ctx;
 }
 
-static bool radius_client_retry_response(fr_bio_t *bio, fr_bio_retry_entry_t **item_p, void *packet_ctx, const void *buffer, UNUSED size_t size)
+static bool radius_client_retry_response(fr_bio_t *bio, fr_bio_retry_entry_t **retry_ctx_p, UNUSED void *packet_ctx, const void *buffer, UNUSED size_t size)
 {
        fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_client_fd_bio_t);
-       fr_radius_client_packet_ctx_t *ctx, *reply_ctx;
        unsigned int code;
        uint8_t *data = UNCONST(uint8_t *, buffer); /* @todo - for verify() */
-       fr_packet_t *packet;
+       fr_radius_id_ctx_t *id_ctx;
 
        /*
         *      We now have a complete packet in our buffer.  Check if it is one we expect.
         */
-       if (!data[0] || (data[0] >= FR_RADIUS_CODE_MAX)) {
-               return false;
-       }
+       fr_assert(data[0] > 0);
+       fr_assert(data[0] < FR_RADIUS_CODE_MAX);
 
        /*
         *      Is the code an allowed reply code?
@@ -193,27 +202,22 @@ static bool radius_client_retry_response(fr_bio_t *bio, fr_bio_retry_entry_t **i
        /*
         *      It's a reply, but not a permitted reply to a particular request.
         *
-        *      @todo - for protocol error, look up original packet code <sigh>
+        *      @todo - Status-Server.  And for protocol error, look up original packet code
         */
-       packet = fr_radius_code_id_find(my->codes, code, data[1]);
-       if (!packet) return false;
-
-       ctx = packet->uctx;
-       reply_ctx = packet_ctx;
+       id_ctx = fr_radius_code_id_find(my->codes, allowed_replies[code], data[1]);
+       if (!id_ctx) return false;
 
        /*
         *      No reply yet, verify the response packet, and save it for later.
         */
-       if (!ctx->reply) {
-               if (fr_radius_verify(data, packet->data + 4,
+       if (!id_ctx->response) {
+               if (fr_radius_verify(data,id_ctx-> packet->data + 4,
                                     my->cfg.verify.secret, my->cfg.verify.secret_len,
                                     my->cfg.verify.require_message_authenticator) < 0) {
                        return false;
                }
 
-               *item_p = ctx->retry_ctx;
-
-               reply_ctx->packet = packet;
+               *retry_ctx_p = id_ctx->retry_ctx;
                return true;
        }
 
@@ -221,37 +225,42 @@ static bool radius_client_retry_response(fr_bio_t *bio, fr_bio_retry_entry_t **i
         *      The reply has the correct ID / Code, but it's not the
         *      same as our previous reply: ignore it.
         */
-       if (memcmp(buffer, ctx->reply, RADIUS_HEADER_LENGTH) != 0) return false;
+       if (memcmp(buffer, id_ctx->response->data, RADIUS_HEADER_LENGTH) != 0) return false;
        
        /*
         *      Tell the caller that it's a duplicate reply.
         */
-       *item_p = ctx->retry_ctx;
+       *retry_ctx_p = id_ctx->retry_ctx;
        return false;
 }
 
-static void radius_client_retry_release(fr_bio_t *bio, void *packet_ctx, UNUSED const void *buffer, UNUSED size_t size, UNUSED fr_bio_retry_release_reason_t reason)
+static void radius_client_retry_release(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, UNUSED fr_bio_retry_release_reason_t reason)
 {
        fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_client_fd_bio_t);
-       fr_radius_client_packet_ctx_t *ctx = packet_ctx;
+       fr_radius_id_ctx_t *id_ctx = retry_ctx->uctx;
 
-       fr_radius_code_id_push(my->codes, ctx->packet);
+       fr_radius_code_id_push(my->codes, id_ctx->packet);
 }
 #endif
 
-int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, fr_packet_t **packet_p,
-                                TALLOC_CTX *pair_ctx, fr_pair_list_t *out)
+int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, void **request_ctx_p, fr_packet_t **packet_p,
+                                TALLOC_CTX *out_ctx, fr_pair_list_t *out)
 {
        ssize_t slen;
        fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
-       fr_packet_t *packet, *reply;
-       fr_radius_client_packet_ctx_t ctx = {};
+       fr_packet_t *reply;
+       fr_radius_id_ctx_t *id_ctx;
+
+       /*
+        *      We don't need to set up response.socket for connected bios.
+        */
+       fr_packet_t response = {};
 
        /*
         *      We read the response packet ctx into our local structure.  If we have a real response, we will
         *      swap to using the request context, and not the response context.
         */
-       slen = fr_bio_read(my->common.bio, &ctx, &my->buffer, sizeof(my->buffer));
+       slen = fr_bio_read(my->common.bio, &response, &my->buffer, sizeof(my->buffer));
        if (!slen) return 0;
 
        if (slen < 0) {
@@ -259,15 +268,21 @@ int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, fr_packet_t **packet_p,
                return slen;
        }
 
-       packet = ctx.packet;
-       fr_assert(packet != NULL);
+       /*
+        *      Use the reply code to look up the original packet code.
+        *
+        *      @todo - see above todo in response().  Maybe cache the id_ctx in "my"?
+        */
+       id_ctx = fr_radius_code_id_find(my->codes, allowed_replies[my->buffer[0]], my->buffer[1]);
+       fr_assert(id_ctx != NULL);
 
        /*
         *      Allocate the new request data structure
         */
-       reply = fr_packet_alloc(packet, false);
+       reply = fr_packet_alloc(id_ctx->packet, false);
        if (!reply) return -1;
-       ctx.reply = reply;
+
+       id_ctx->response = reply;
 
        /*
         *      This is for connected sockets.
@@ -289,12 +304,12 @@ int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, fr_packet_t **packet_p,
        /*
         *      If this fails, we're out of memory.
         */
-       if (fr_radius_decode_simple(pair_ctx, out, reply->data, reply->data_len,
-                                   packet->vector, (char const *) my->cfg.verify.secret) < 0) {
+       if (fr_radius_decode_simple(out_ctx, out, reply->data, reply->data_len,
+                                   id_ctx->packet->vector, (char const *) my->cfg.verify.secret) < 0) {
                fr_assert(0);
        }
 
-       reply->uctx = packet->uctx;
+       *request_ctx_p = id_ctx->request_ctx;
        *packet_p = reply;
 
        return 1;
index c2f0cfa67e4cbc84d94a348d64c921b0ae4e81e8..7ec66336e7d40d76d726bded02e835c1c2e9106e 100644 (file)
@@ -39,13 +39,6 @@ typedef struct {
        fr_retry_config_t  retry[FR_RADIUS_CODE_MAX];   //!< default retry configuration for each packet type
 } fr_radius_client_config_t;
 
-typedef struct {
-       fr_bio_retry_entry_t    *retry_ctx;
-
-       fr_packet_t     *packet;
-       fr_packet_t     *reply;
-} fr_radius_client_packet_ctx_t;
-
 fr_bio_packet_t *fr_radius_client_bio_alloc(TALLOC_CTX *ctx, fr_radius_client_config_t *cfg, fr_bio_fd_config_t const *fd_cfg) CC_HINT(nonnull);
 
 fr_bio_t       *fr_radius_client_bio_get_fd(fr_bio_packet_t *bio);
index c96b99b6630bc23c9cd267d3119550a83b69326b..3edf4ac1d818fa310d0af7e588fe66d723f71fd0 100644 (file)
@@ -54,6 +54,6 @@ typedef struct {
 
 fr_radius_client_fd_bio_t *fr_radius_client_fd_bio_alloc(TALLOC_CTX *ctx, size_t read_size, fr_radius_client_config_t *cfg, fr_bio_fd_config_t const *fd_cfg) CC_HINT(nonnull);
 
-int    fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, fr_packet_t *packet, fr_pair_list_t *list);
+int    fr_radius_client_fd_bio_write(fr_radius_client_fd_bio_t *my, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list);
 
-int    fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, fr_packet_t **packet_p, TALLOC_CTX *ctx, fr_pair_list_t *list);
+int    fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, void **request_ctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out);
index 001e148be45275011b3f99bacb0d39ed0be8bc16..207f686d8c1519f292f0af0ac43f5d0479699d35 100644 (file)
@@ -31,7 +31,7 @@ RCSID("$Id$")
 /**  Allocate an ID, and write one packet.
  *
  */
-static int fr_radius_client_tcp_bio_write(fr_bio_packet_t *bio, fr_packet_t *packet, fr_pair_list_t *list)
+static int fr_radius_client_tcp_bio_write(fr_bio_packet_t *bio, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
 {
        fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
 
@@ -40,7 +40,7 @@ static int fr_radius_client_tcp_bio_write(fr_bio_packet_t *bio, fr_packet_t *pac
         */
        fr_assert(!packet->data);
 
-       return fr_radius_client_fd_bio_write(my, packet, list);
+       return fr_radius_client_fd_bio_write(my, request_ctx, packet, list);
 }
 
 /** Allocate a RADIUS bio for writing client packets
index f50194f8faf9edd65063f4d49d9ccb525d9cf38c..c6b4b5f58efc57f29275387d0ab84eadff763025 100644 (file)
@@ -31,12 +31,12 @@ RCSID("$Id$")
 /**  Allocate an ID, and write one packet.
  *
  */
-static int fr_radius_client_udp_bio_write(fr_bio_packet_t *bio, fr_packet_t *packet, fr_pair_list_t *list)
+static int fr_radius_client_udp_bio_write(fr_bio_packet_t *bio, void *request_ctx, fr_packet_t *packet, fr_pair_list_t *list)
 {
        ssize_t slen;
        fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
 
-       if (!packet->data) return fr_radius_client_fd_bio_write(my, packet, list);
+       if (!packet->data) return fr_radius_client_fd_bio_write(my, request_ctx, packet, list);
 
        slen = fr_bio_write(my->common.bio, &packet->socket, packet->data, packet->data_len);
        if (slen <= 0) return -1;
index 6576c8c90d1c6bedec25cbde2f70be7f37d37de8..9d6839982e0c07bfa162e5d118185b02f3a7df55 100644 (file)
@@ -32,7 +32,7 @@ struct fr_radius_id_s {
        int                     free_start;
        int                     free_end;
 
-       fr_packet_t             *packet[256];   //!< pointer to packet data
+       fr_radius_id_ctx_t      id[256];        //!< pointers to request / reply data
 
        int                     free_ids[256];
 };
@@ -64,7 +64,7 @@ fr_radius_id_t *fr_radius_id_alloc(TALLOC_CTX *ctx)
 /** Allocate an ID for a packet, using LRU
  *
  */
-int fr_radius_id_pop(fr_radius_id_t *track, fr_packet_t *packet)
+fr_radius_id_ctx_t *fr_radius_id_pop(fr_radius_id_t *track, fr_packet_t *packet)
 {
        int id;
 
@@ -72,7 +72,7 @@ int fr_radius_id_pop(fr_radius_id_t *track, fr_packet_t *packet)
        fr_assert(id >= 0);
        fr_assert(id < 256);
 
-       fr_assert(!track->packet[id]);
+       fr_assert(!track->id[id].packet);
 
        track->free_ids[track->free_start] = -1;
 
@@ -82,10 +82,12 @@ int fr_radius_id_pop(fr_radius_id_t *track, fr_packet_t *packet)
        fr_assert(track->num_free_ids > 0);
        track->num_free_ids--;
 
-       track->packet[id] = packet;
+       track->id[id] = (fr_radius_id_ctx_t) {
+               .packet = packet,
+       };
        packet->id = id;
 
-       return 0;
+       return &track->id[id];
 }
 
 /** De-allocate an ID for a packet, using LRU
@@ -96,7 +98,7 @@ void fr_radius_id_push(fr_radius_id_t *track, fr_packet_t const *packet)
        fr_assert(packet->id >= 0);
        fr_assert(packet->id < 256);
 
-       fr_assert(track->packet[packet->id] == packet);
+       fr_assert(track->id[packet->id].packet == packet);
        fr_assert(track->num_free_ids < 256);
        fr_assert(track->free_start != track->free_end);
        fr_assert(track->free_end >= 0);
@@ -108,14 +110,14 @@ void fr_radius_id_push(fr_radius_id_t *track, fr_packet_t const *packet)
        track->free_end++;
        track->free_end &= 0xff;
 
-       track->packet[packet->id] = NULL;
+       track->id[packet->id].packet = NULL;
        track->num_free_ids++;
 }
 
-fr_packet_t *fr_radius_id_find(fr_radius_id_t *track, int id)
+fr_radius_id_ctx_t *fr_radius_id_find(fr_radius_id_t *track, int id)
 {
        fr_assert(id >= 0);
        fr_assert(id < 256);
 
-       return track->packet[id];
+       return &track->id[id];
 }
index 9cc806168fd2553a6ea597e3a3fc1b5cee9712d1..53e9f356c5632d126ecae9e716fcbc68059cebe7 100644 (file)
@@ -31,13 +31,20 @@ typedef struct fr_radius_id_s fr_radius_id_t;
 
 typedef fr_radius_id_t *fr_radius_code_id_t[FR_RADIUS_CODE_MAX];
 
+typedef struct {
+       void            *request_ctx;           //!< for the application to track
+       fr_packet_t     *packet;                //!< outgoing packet
+       fr_packet_t     *response;              //!< response to outgoing packet
+       void            *retry_ctx;             //!< to find the retry information
+} fr_radius_id_ctx_t;
+
 fr_radius_id_t *fr_radius_id_alloc(TALLOC_CTX *ctx);
 
-int            fr_radius_id_pop(fr_radius_id_t *track, fr_packet_t *packet) CC_HINT(nonnull);
+fr_radius_id_ctx_t *fr_radius_id_pop(fr_radius_id_t *track, fr_packet_t *packet) CC_HINT(nonnull);
 
 void           fr_radius_id_push(fr_radius_id_t *track, fr_packet_t const *packet) CC_HINT(nonnull);
 
-fr_packet_t    *fr_radius_id_find(fr_radius_id_t *track, int id) CC_HINT(nonnull);
+fr_radius_id_ctx_t *fr_radius_id_find(fr_radius_id_t *track, int id) CC_HINT(nonnull);
 
 static inline CC_HINT(nonnull) int fr_radius_code_id_alloc(TALLOC_CTX *ctx, fr_radius_code_id_t codes, int code)
 {
@@ -52,7 +59,7 @@ static inline CC_HINT(nonnull) int fr_radius_code_id_alloc(TALLOC_CTX *ctx, fr_r
        return 0;
 }
 
-static inline CC_HINT(nonnull) int fr_radius_code_id_pop(fr_radius_code_id_t codes, fr_packet_t *packet)
+static inline CC_HINT(nonnull) fr_radius_id_ctx_t *fr_radius_code_id_pop(fr_radius_code_id_t codes, fr_packet_t *packet)
 {
        fr_assert(packet->code > 0);
        fr_assert(packet->code < FR_RADIUS_CODE_MAX);
@@ -72,7 +79,7 @@ static inline CC_HINT(nonnull) void fr_radius_code_id_push(fr_radius_code_id_t c
        fr_radius_id_push(codes[packet->code], packet);
 }
 
-static inline CC_HINT(nonnull) fr_packet_t *fr_radius_code_id_find(fr_radius_code_id_t codes, int code, int id)
+static inline CC_HINT(nonnull) fr_radius_id_ctx_t *fr_radius_code_id_find(fr_radius_code_id_t codes, int code, int id)
 {
        fr_assert(code > 0);
        fr_assert(code < FR_RADIUS_CODE_MAX);