]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add retry && release callbacks for packet bio
authorAlan T. DeKok <aland@freeradius.org>
Wed, 22 May 2024 18:50:31 +0000 (14:50 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 22 May 2024 18:50:31 +0000 (14:50 -0400)
so that the application can do something (e.g. print stuff)
on retry.  And then clean up the packet on release.

It's partially glued into radclint-ng, via the simple expedient
of having an assert() on release.  Later code will add actual
cleanups

src/bin/radclient-ng.c
src/lib/bio/packet.h
src/lib/bio/retry.c
src/protocols/radius/client.c
src/protocols/radius/client.h

index af227f0c3af3da058efe58819cfe426e34071057..47406b0a8651a7ec9b458a64728c81bd03541849 100644 (file)
@@ -929,6 +929,22 @@ static int8_t request_cmp(void const *one, void const *two)
        return fr_value_box_cmp(&vp1->data, &vp2->data);
 }
 
+static void client_retry_log(UNUSED fr_bio_packet_t *client, fr_packet_t *packet)
+{
+       rc_request_t *request = packet->uctx;
+
+       DEBUG("Timeout - resending packet");
+
+       // @todo - log the actual / updated Acct-Delay-Time?
+
+       fr_radius_packet_log(&default_log, request->packet, &request->request_pairs, false);
+}
+
+static void client_release(UNUSED fr_bio_packet_t *client, UNUSED fr_packet_t *packet)
+{
+       fr_assert(0);
+}
+
 
 /*
  *     Send one packet.
@@ -1697,9 +1713,12 @@ int main(int argc, char **argv)
         *      Set callbacks so that the socket is automatically
         *      paused or resumed when the socket becomes writeable.
         */
-       client_config.pause_resume_cfg = (fr_bio_packet_cb_funcs_t) {
+       client_config.packet_cb_cfg = (fr_bio_packet_cb_funcs_t) {
                .write_blocked = client_bio_write_pause,
                .write_resume = client_bio_write_resume,
+
+               .retry = (fr_debug_lvl > 0) ? client_retry_log : NULL,
+               .release = client_release,
        };
 
        /*
index 5654f40f616ff27f6303e11e7b3a60f2b6a508c7..563c78c772cad1b750ba2b700328dc66b3c665d8 100644 (file)
@@ -56,24 +56,24 @@ typedef int (*fr_bio_packet_read_t)(fr_bio_packet_t *bio, void **request_ctx_p,
  */
 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.
+/** Signal an outgoing packet.
  *
  * @param bio          the packet-based bio
  * @param packet       the output packet descriptor.  Contains raw protocol data (IDs, counts, etc.)
- * @return
- *     - <0 on error
- *     - 0 for success
  */
-typedef int (*fr_bio_packet_release_t)(fr_bio_packet_t *bio, fr_packet_t *packet);
+typedef void (*fr_bio_packet_signal_t)(fr_bio_packet_t *bio, fr_packet_t *packet);
 
-typedef void (*fr_bio_packet_signal_t)(fr_bio_packet_t *bio);
+typedef void (*fr_bio_packet_io_t)(fr_bio_packet_t *bio);
 
 typedef struct {
-       fr_bio_packet_signal_t  read_blocked;
-       fr_bio_packet_signal_t  write_blocked;
+       fr_bio_packet_io_t      read_blocked;
+       fr_bio_packet_io_t      write_blocked;
+
+       fr_bio_packet_io_t      read_resume;
+       fr_bio_packet_io_t      write_resume;
 
-       fr_bio_packet_signal_t  read_resume;
-       fr_bio_packet_signal_t  write_resume;
+       fr_bio_packet_signal_t  retry;
+       fr_bio_packet_signal_t  release;
 } fr_bio_packet_cb_funcs_t;
 
 struct fr_bio_packet_s {
index 9657a5dd6cb1fda6914d75d67c4b2ef5796d339b..72a1a84f300ecfefbd1333a057d01069d1e4fdf8 100644 (file)
@@ -205,7 +205,7 @@ static int fr_bio_retry_write_item(fr_bio_retry_t *my, fr_bio_retry_entry_t *ite
         */
        state = fr_retry_next(&item->retry, now);
        if (state != FR_RETRY_CONTINUE) {
-               fr_bio_retry_release(my, item, (fr_bio_retry_release_reason_t) (item->retry.replies > 0));
+               fr_bio_retry_release(my, item, (item->retry.replies > 0) ? FR_BIO_RETRY_DONE : FR_BIO_RETRY_NO_REPLY);
                return 1;
        }
 
index 023ff674f702edc027c6de666a95a05117dea539..3fcc934d102dca4684fb46238e8db30ee527c2ba 100644 (file)
@@ -43,7 +43,7 @@ static void radius_client_retry_sent(fr_bio_t *bio, void *packet_ctx, const void
                                     fr_bio_retry_entry_t *retry_ctx);
 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);
 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);
-
+static ssize_t radius_client_retry(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, UNUSED const void *buffer, NDEBUG_UNUSED size_t size);
 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)
 {
        fr_assert(fd_cfg->type == FR_BIO_FD_CONNECTED);
@@ -72,6 +72,7 @@ fr_radius_client_fd_bio_t *fr_radius_client_fd_bio_alloc(TALLOC_CTX *ctx, size_t
 {
        int i;
        fr_radius_client_fd_bio_t *my;
+       fr_bio_retry_rewrite_t rewrite = NULL;
 
        fr_assert(fd_cfg->type == FR_BIO_FD_CONNECTED);
 
@@ -103,8 +104,8 @@ fr_radius_client_fd_bio_t *fr_radius_client_fd_bio_alloc(TALLOC_CTX *ctx, size_t
        /*
         *      Set up read / write blocked / resume callbacks.
         */
-       if (cfg->pause_resume_cfg.write_blocked || cfg->pause_resume_cfg.read_blocked) {
-               fr_radius_client_bio_cb_set((fr_bio_packet_t *) my, &cfg->pause_resume_cfg);
+       if (cfg->packet_cb_cfg.write_blocked || cfg->packet_cb_cfg.read_blocked) {
+               fr_radius_client_bio_cb_set((fr_bio_packet_t *) my, &cfg->packet_cb_cfg);
        }
 
        my->info.fd_info = fr_bio_fd_info(my->fd);
@@ -119,8 +120,10 @@ fr_radius_client_fd_bio_t *fr_radius_client_fd_bio_alloc(TALLOC_CTX *ctx, size_t
        if (!my->mem) goto fail;
        my->mem->uctx = &my->cfg.verify;
 
+       if (cfg->packet_cb_cfg.retry) rewrite = radius_client_retry;
+
        my->retry = fr_bio_retry_alloc(my, 256, radius_client_retry_sent, radius_client_retry_response,
-                                      NULL, radius_client_retry_release, &cfg->retry_cfg, my->mem);
+                                      rewrite, radius_client_retry_release, &cfg->retry_cfg, my->mem);
        if (!my->retry) goto fail;
        my->retry->uctx = my;
        
@@ -267,6 +270,25 @@ 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 ssize_t radius_client_retry(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, UNUSED const void *buffer, NDEBUG_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_id_ctx_t *id_ctx = retry_ctx->uctx;
+       fr_packet_t *packet = id_ctx->packet;
+
+       fr_assert(packet->data_len == size);
+
+       fr_assert(my->cfg.packet_cb_cfg.retry);
+
+       my->cfg.packet_cb_cfg.retry(&my->common, id_ctx->packet);
+
+       /*
+        *      Note do do NOT ball fr_bio_write(), because that will treat the packet as a new one!
+        */
+       return fr_bio_retry_rewrite(bio, retry_ctx, packet->data, packet->data_len);
+}
+
+
 static ssize_t radius_client_rewrite_acct(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, UNUSED const void *buffer, NDEBUG_UNUSED size_t size)
 {
        fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_client_fd_bio_t);
@@ -307,6 +329,11 @@ static ssize_t radius_client_rewrite_acct(fr_bio_t *bio, fr_bio_retry_entry_t *r
        (void) fr_radius_sign(packet->data, NULL,
                              (uint8_t const *) my->cfg.verify.secret, my->cfg.verify.secret_len);
 
+       /*
+        *      Signal that the packet has been retried.
+        */
+       if (my->cfg.packet_cb_cfg.retry) my->cfg.packet_cb_cfg.retry(&my->common, id_ctx->packet);
+
        /*
         *      Note do do NOT ball fr_bio_write(), because that will treat the packet as a new one!
         */
@@ -434,13 +461,20 @@ static bool radius_client_retry_response(fr_bio_t *bio, fr_bio_retry_entry_t **r
        return false;
 }
 
-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)
+static void radius_client_retry_release(fr_bio_t *bio, fr_bio_retry_entry_t *retry_ctx, 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_id_ctx_t *id_ctx = retry_ctx->uctx;
 
        fr_assert(id_ctx->packet == retry_ctx->packet_ctx);
 
+       fprintf(stderr, "RELEASE %p %d\n", my->cfg.packet_cb_cfg.release, reason);
+
+       /*
+        *      Tell the application that this packet did not see a reply/
+        */
+       if (my->cfg.packet_cb_cfg.release && (reason == FR_BIO_RETRY_NO_REPLY)) my->cfg.packet_cb_cfg.release(&my->common, id_ctx->packet);
+
        fr_radius_code_id_push(my->codes, id_ctx->packet);
 
        /*
index b51e7c0daebcad5051d9e5f648eae8556bd2b1d9..8c2f7e79f43604876ee1a1ea88123147e02294d2 100644 (file)
@@ -38,7 +38,7 @@ typedef struct {
 
        fr_bio_retry_config_t   retry_cfg;
 
-       fr_bio_packet_cb_funcs_t pause_resume_cfg;
+       fr_bio_packet_cb_funcs_t packet_cb_cfg;
 
        bool                    add_proxy_state;
        uint32_t                proxy_state;