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: 170d9d103bbae2f33781296e65eac7197f07f076 $
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: 170d9d103bbae2f33781296e65eac7197f07f076 $")
26
27#include <freeradius-devel/radius/id.h>
28
30 int num_free_ids; //!< number of used 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 id = track->free_ids[track->free_start];
94 fr_assert(id >= 0);
95 fr_assert(id < 256);
96
97 fr_assert(!track->id[id].packet);
98
99 track->free_ids[track->free_start] = -1;
100
101 track->free_start++;
102 track->free_start &= 0xff;
103
104 fr_assert(track->num_free_ids > 0);
105 track->num_free_ids--;
106
107 track->id[id] = (fr_radius_id_ctx_t) {
108 .packet = packet,
109 };
110 packet->id = id;
111
112 return &track->id[id];
113}
114
115/** De-allocate an ID for a packet, using LRU
116 *
117 */
119{
120 fr_assert(packet->id >= 0);
121 fr_assert(packet->id < 256);
122
123 fr_assert(track->id[packet->id].packet == packet);
124 fr_assert(track->num_free_ids < 256);
125 fr_assert(track->free_start != track->free_end);
126 fr_assert(track->free_end >= 0);
127 fr_assert(track->free_end < 256);
128 fr_assert(track->free_ids[track->free_end] == -1);
129
130 track->free_ids[track->free_end] = packet->id;
131
132 track->free_end++;
133 track->free_end &= 0xff;
134
135 track->id[packet->id].packet = NULL;
136 track->num_free_ids++;
137}
138
140{
141 fr_assert(id >= 0);
142 fr_assert(id < 256);
143
144 return &track->id[id];
145}
146
147/** Forces the next ID to be the given one
148 *
149 */
151{
152 int i, first;
153
154 fr_assert(id >= 0);
155 fr_assert(id < 256);
156
157 for (i = 0; i < 256; i++) {
158 if (track->free_ids[(track->free_start + i) & 0xff] != id) continue;
159
160 /*
161 * It's already the first one. We don't need to do any more.
162 */
163 if (i == 0) return 0;
164
165 first = track->free_ids[track->free_start];
166 track->free_ids[track->free_start] = id;
167 track->free_ids[(track->free_start + i) & 0xff] = first;
168
169 return 0;
170 }
171
172 fr_strerror_const("Cannot assign ID");
173 return -1;
174}
#define RCSID(id)
Definition build.h:483
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:118
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:139
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:150
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 used 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