The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
id.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: ac65dd17667dabad165417f77b45366d3f77e2eb $
19 *
20 * @file protocols/radius/id.c
21 * @brief Functions to allocate 8-bit IDs for a particular socket.
22 *
23 * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
24 */
25RCSID("$Id: ac65dd17667dabad165417f77b45366d3f77e2eb $")
26
27#include <freeradius-devel/radius/id.h>
28
30 int num_free_ids; //!< number of free IDs
31
34
35 fr_radius_id_ctx_t id[256]; //!< pointers to request / reply data
36
37 int free_ids[256];
38};
39
40
41
42/** Allocate a tracking structure for one packet code.
43 *
44 */
46{
47 uint32_t i;
48 fr_radius_id_t *track;
49
50 track = talloc_zero(ctx, fr_radius_id_t);
51 if (!track) return NULL;
52
53 track->num_free_ids = 256;
54 track->free_start = 0;
55 track->free_end = 0;
56
57 for (i = 0; i < 256; i++) {
58 track->free_ids[i] = i;
59 }
60
61 /*
62 * Shuffle the entirs using a Fisher-Yates shuffle.
63 *
64 * We loop from i=255..1, choosing random numbers j, such that 0 <= j <= i
65 * And then swap a[j],a[i]
66 *
67 * We choose a 32-bit random number, and then take the modulo of that and i+1. Which means that
68 * the resulting random number j is [0..i], whereas taking the modulo with i, then the random
69 * number j will instead be chosen to be [0..i)
70 */
71 for (i = 255; i >= 1; i--) {
72 uint32_t j = fr_rand() % (i + 1); /* small bias, but we don't care much */
73 int tmp;
74
75 if (j == i) continue;
76
77 tmp = track->free_ids[j];
78 track->free_ids[j] = track->free_ids[i];
79 track->free_ids[i] = tmp;
80 }
81
82
83 return track;
84}
85
86/** Allocate an ID for a packet, using LRU
87 *
88 */
90{
91 int id;
92
93 if (track->num_free_ids == 0) return NULL;
94
95 id = track->free_ids[track->free_start];
96 fr_assert(id >= 0);
97 fr_assert(id < 256);
98
99 fr_assert(!track->id[id].packet);
100
101 track->free_ids[track->free_start] = -1;
102
103 track->free_start++;
104 track->free_start &= 0xff;
105
106 fr_assert(track->num_free_ids > 0);
107 track->num_free_ids--;
108
109 track->id[id] = (fr_radius_id_ctx_t) {
110 .packet = packet,
111 };
112 packet->id = id;
113
114 return &track->id[id];
115}
116
117/** De-allocate an ID for a packet, using LRU
118 *
119 */
121{
122 fr_assert(packet->id >= 0);
123 fr_assert(packet->id < 256);
124
125 fr_assert(track->id[packet->id].packet == packet);
126 fr_assert(track->num_free_ids < 256);
127 fr_assert(track->free_end >= 0);
128 fr_assert(track->free_end < 256);
129 fr_assert(track->free_ids[track->free_end] == -1);
130
131 track->free_ids[track->free_end] = packet->id;
132
133 track->free_end++;
134 track->free_end &= 0xff;
135
136 track->id[packet->id].packet = NULL;
137 track->num_free_ids++;
138}
139
141{
142 fr_assert(id >= 0);
143 fr_assert(id < 256);
144
145 return &track->id[id];
146}
147
148/** Forces the next ID to be the given one
149 *
150 */
152{
153 int i, first;
154
155 fr_assert(id >= 0);
156 fr_assert(id < 256);
157
158 for (i = 0; i < 256; i++) {
159 if (track->free_ids[(track->free_start + i) & 0xff] != id) continue;
160
161 /*
162 * It's already the first one. We don't need to do any more.
163 */
164 if (i == 0) return 0;
165
166 first = track->free_ids[track->free_start];
167 track->free_ids[track->free_start] = id;
168 track->free_ids[(track->free_start + i) & 0xff] = first;
169
170 return 0;
171 }
172
173 fr_strerror_const("Cannot assign ID");
174 return -1;
175}
#define RCSID(id)
Definition build.h:487
unsigned int uint32_t
void fr_radius_id_push(fr_radius_id_t *track, fr_packet_t const *packet)
De-allocate an ID for a packet, using LRU.
Definition id.c:120
int free_ids[256]
Definition id.c:37
int free_start
Definition id.c:32
fr_radius_id_ctx_t * fr_radius_id_pop(fr_radius_id_t *track, fr_packet_t *packet)
Allocate an ID for a packet, using LRU.
Definition id.c:89
fr_radius_id_ctx_t * fr_radius_id_find(fr_radius_id_t *track, int id)
Definition id.c:140
fr_radius_id_t * fr_radius_id_alloc(TALLOC_CTX *ctx)
Allocate a tracking structure for one packet code.
Definition id.c:45
int fr_radius_id_force(fr_radius_id_t *track, int id)
Forces the next ID to be the given one.
Definition id.c:151
int free_end
Definition id.c:33
fr_radius_id_ctx_t id[256]
pointers to request / reply data
Definition id.c:35
int num_free_ids
number of free IDs
Definition id.c:30
fr_packet_t * packet
outgoing packet
Definition id.h:36
#define fr_assert(_expr)
Definition rad_assert.h:38
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:105
int id
Packet ID (used to link requests/responses).
Definition packet.h:60
#define fr_strerror_const(_msg)
Definition strerror.h:223