From: Alan T. DeKok Date: Wed, 13 Mar 2024 21:15:57 +0000 (-0400) Subject: more rework to add request_ctx for packet BIOs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d490128f344aafcae5fd7f7451c1a22be3b8d979;p=thirdparty%2Ffreeradius-server.git more rework to add request_ctx for packet BIOs so that we can not only encode a packet + pairs, but also associate that with a larger request context --- diff --git a/src/lib/bio/packet.h b/src/lib/bio/packet.h index 4692dc84b2b..ec0b537f87a 100644 --- a/src/lib/bio/packet.h +++ b/src/lib/bio/packet.h @@ -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); } diff --git a/src/lib/bio/retry.c b/src/lib/bio/retry.c index 5c764506b6c..f939faf7ca2 100644 --- a/src/lib/bio/retry.c +++ b/src/lib/bio/retry.c @@ -23,12 +23,14 @@ */ #include -#include #include #include #include #include +#define _BIO_RETRY_PRIVATE +#include + 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; diff --git a/src/lib/bio/retry.h b/src/lib/bio/retry.h index 888e0e3a824..6e4ebfbc3a7 100644 --- a/src/lib/bio/retry.h +++ b/src/lib/bio/retry.h @@ -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, diff --git a/src/protocols/radius/client.c b/src/protocols/radius/client.c index 44ac6dbab85..56192a26629 100644 --- a/src/protocols/radius/client.c +++ b/src/protocols/radius/client.c @@ -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 + * @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; diff --git a/src/protocols/radius/client.h b/src/protocols/radius/client.h index c2f0cfa67e4..7ec66336e7d 100644 --- a/src/protocols/radius/client.h +++ b/src/protocols/radius/client.h @@ -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); diff --git a/src/protocols/radius/client_priv.h b/src/protocols/radius/client_priv.h index c96b99b6630..3edf4ac1d81 100644 --- a/src/protocols/radius/client_priv.h +++ b/src/protocols/radius/client_priv.h @@ -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); diff --git a/src/protocols/radius/client_tcp.c b/src/protocols/radius/client_tcp.c index 001e148be45..207f686d8c1 100644 --- a/src/protocols/radius/client_tcp.c +++ b/src/protocols/radius/client_tcp.c @@ -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 diff --git a/src/protocols/radius/client_udp.c b/src/protocols/radius/client_udp.c index f50194f8faf..c6b4b5f58ef 100644 --- a/src/protocols/radius/client_udp.c +++ b/src/protocols/radius/client_udp.c @@ -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; diff --git a/src/protocols/radius/id.c b/src/protocols/radius/id.c index 6576c8c90d1..9d6839982e0 100644 --- a/src/protocols/radius/id.c +++ b/src/protocols/radius/id.c @@ -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]; } diff --git a/src/protocols/radius/id.h b/src/protocols/radius/id.h index 9cc806168fd..53e9f356c56 100644 --- a/src/protocols/radius/id.h +++ b/src/protocols/radius/id.h @@ -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);