The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
client.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: 64c45ff76169ad20d4032349ba1daf1d15a0042a $
19  *
20  * @file protocols/radius/client.c
21  * @brief Functions to support RADIUS bio handlers for client sockets
22  *
23  * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
24  */
25 RCSID("$Id: 64c45ff76169ad20d4032349ba1daf1d15a0042a $")
26 
27 #include <freeradius-devel/radius/client.h>
28 #include <freeradius-devel/radius/client_udp.h>
29 #include <freeradius-devel/radius/client_tcp.h>
30 #include <freeradius-devel/radius/client_priv.h>
31 
32 static void radius_client_retry_sent(fr_bio_t *bio, void *packet_ctx, const void *buffer, UNUSED size_t size,
33  fr_bio_retry_entry_t *retry_ctx);
34 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);
36 
38 {
40 
41  if (fd_cfg->path || fd_cfg->filename) {
42  fr_strerror_const("Domain sockets and files are not supported");
43  return NULL;
44  }
45 
46  if (fd_cfg->socket_type == SOCK_DGRAM) return fr_radius_client_udp_bio_alloc(ctx, cfg, fd_cfg);
47 
48  return fr_radius_client_tcp_bio_alloc(ctx, cfg, fd_cfg);
49 }
50 
52 {
53  if (fr_bio_shutdown(my->common.bio) < 0) return -1;
54 
55  if (fr_bio_free(my->common.bio) < 0) return -1;
56 
57  return 0;
58 }
59 
60 
62 {
63  int i;
65 
67 
68  my = talloc_zero(ctx, fr_radius_client_fd_bio_t);
69  if (!my) return NULL;
70 
71  /*
72  * Allocate tracking for all of the packets.
73  */
74  for (i = 1; i < FR_RADIUS_CODE_MAX; i++) {
75  if (!cfg->outgoing[i]) continue;
76 
77  my->codes[i] = fr_radius_id_alloc(my);
78  if (!my->codes[i]) goto fail;
79  }
80 
81  my->fd = fr_bio_fd_alloc(my, NULL, fd_cfg, 0);
82  if (!my->fd) {
83  fail:
84  talloc_free(my);
85  return NULL;
86  }
87 
88  my->fd_info = fr_bio_fd_info(my->fd);
89  fr_assert(my->fd_info != NULL);
90 
91  my->reply_socket = my->fd_info->socket;
92  if ((my->reply_socket.af == AF_INET) || (my->reply_socket.af == AF_INET6)) {
94  }
95 
96  my->mem = fr_bio_mem_alloc(my, read_size, 2 * 4096, my->fd);
97  if (!my->mem) goto fail;
98  my->mem->uctx = &my->cfg.verify;
99 
101  NULL, radius_client_retry_release, &cfg->retry_cfg, my->mem);
102  if (!my->retry) goto fail;
103  my->retry->uctx = my;
104 
105  my->cfg = *cfg;
106 
107  my->common.bio = my->retry;
108 
109  /*
110  * Set up the connected status.
111  */
113 
114  talloc_set_destructor(my, _radius_client_fd_bio_free);
115 
116  return my;
117 }
118 
120 {
121  ssize_t slen;
122  fr_radius_id_ctx_t *id_ctx;
123 
124  fr_assert(!packet->data);
125 
126  fr_assert(packet->code > 0);
127  fr_assert(packet->code < FR_RADIUS_CODE_MAX);
128 
129  if (!my->codes[packet->code]) {
130  fr_strerror_printf("Outgoing packet code %s is disallowed by the configuration",
131  fr_radius_packet_name[packet->code]);
132  return fr_bio_error(GENERIC);
133  }
134 
135  id_ctx = fr_radius_code_id_pop(my->codes, packet);
136  if (!id_ctx) {
137  /*
138  * Try to cancel the oldest one.
139  */
140  if (fr_bio_retry_entry_cancel(my->retry, NULL) < 1) {
141  all_ids_used:
142  fr_strerror_const("All IDs are in use");
143  return fr_bio_error(GENERIC);
144  }
145 
146  id_ctx = fr_radius_code_id_pop(my->codes, packet);
147  if (!id_ctx) goto all_ids_used;
148  }
149  id_ctx->request_ctx = request_ctx;
150  fr_assert(id_ctx->packet == packet);
151 
152  /*
153  * Encode the packet.
154  */
155  if (fr_packet_encode(packet, list, NULL, (char const *) my->cfg.verify.secret) < 0) {
156  fail:
157  fr_radius_code_id_push(my->codes, packet);
158  return fr_bio_error(GENERIC);
159  }
160 
161  if (fr_packet_sign(packet, NULL, (char const *) my->cfg.verify.secret) < 0) goto fail;
162 
163  slen = fr_bio_write(my->common.bio, &packet->socket, packet->data, packet->data_len);
164  if (slen < 0) {
165  fr_radius_code_id_push(my->codes, packet);
166  return slen;
167  }
168 
169  /*
170  * Didn't write anything, that's a blocking error.
171  */
172  if (slen == 0) {
173  fr_radius_code_id_push(my->codes, packet);
174  return fr_bio_error(IO_WOULD_BLOCK);
175  }
176 
177  my->info.outstanding++;
178 
179  return 0;
180 }
181 
186 
188 
191 
194 
196 };
197 
198 static void radius_client_retry_sent(fr_bio_t *bio, void *packet_ctx, const void *buffer, UNUSED size_t size,
199  fr_bio_retry_entry_t *retry_ctx)
200 {
201  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_client_fd_bio_t);
202  fr_radius_id_ctx_t *id_ctx;
203  uint8_t const *data = buffer;
204 
205  id_ctx = fr_radius_code_id_find(my->codes, data[0], data[1]);
206  fr_assert(id_ctx != NULL);
207 
208  id_ctx->packet = packet_ctx;
209  id_ctx->retry_ctx = retry_ctx;
210 
211  retry_ctx->uctx = id_ctx;
212 
213  (void) fr_bio_retry_entry_start(bio, retry_ctx, &my->cfg.retry[data[0]]);
214 
215  /*
216  * @todo - set this for Accounting-Request packets which have Acct-Delay-Time we need to track
217  * where the Acct-Delay-Time is in the packet, along with its original value, and then we can use
218  * the #fr_retry_t to discover how many seconds to add to Acct-Delay-Time.
219  */
220  retry_ctx->rewrite = NULL;
221 
222 // if (buffer[0] != FR_RADIUS_CODE_ACCOUNTING_REQUEST) return;
223 }
224 
225 static bool radius_client_retry_response(fr_bio_t *bio, fr_bio_retry_entry_t **retry_ctx_p, void *packet_ctx, const void *buffer, UNUSED size_t size)
226 {
227  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_client_fd_bio_t);
228  unsigned int code;
229  uint8_t *data = UNCONST(uint8_t *, buffer); /* @todo - for verify() */
230  fr_radius_id_ctx_t *id_ctx;
231  fr_packet_t *response = packet_ctx;
232 
233  /*
234  * We now have a complete packet in our buffer. Check if it is one we expect.
235  */
236  fr_assert(data[0] > 0);
238 
239  /*
240  * Is the code an allowed reply code?
241  */
242  code = allowed_replies[data[0]];
243  if (!code) return false;
244 
245  /*
246  * It's a reply, but not a permitted reply to a particular request.
247  *
248  * @todo - Status-Server. And for protocol error, look up original packet code
249  */
250  id_ctx = fr_radius_code_id_find(my->codes, code, data[1]);
251  if (!id_ctx) return false;
252 
253  /*
254  * No reply yet, verify the response packet, and save it for later.
255  */
256  if (!id_ctx->response) {
257  if (fr_radius_verify(data, id_ctx->packet->data + 4,
260  return false;
261  }
262 
263  *retry_ctx_p = id_ctx->retry_ctx;
264  response->uctx = id_ctx->packet;
265 
266  fr_assert(my->info.outstanding > 0);
267  my->info.outstanding--;
268  return true;
269  }
270 
271  /*
272  * The reply has the correct ID / Code, but it's not the
273  * same as our previous reply: ignore it.
274  */
275  if (memcmp(buffer, id_ctx->response->data, RADIUS_HEADER_LENGTH) != 0) return false;
276 
277  /*
278  * Tell the caller that it's a duplicate reply.
279  */
280  *retry_ctx_p = id_ctx->retry_ctx;
281  return false;
282 }
283 
285 {
286  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_client_fd_bio_t);
287  fr_radius_id_ctx_t *id_ctx = retry_ctx->uctx;
288 
289  fr_assert(id_ctx->packet == retry_ctx->packet_ctx);
290 
291  fr_radius_code_id_push(my->codes, id_ctx->packet);
292 
293  /*
294  * We're no longer retrying this packet.
295  *
296  * However, we leave id_ctx->request_ctx and id_ctx->packet around, because the other code still
297  * needs it.
298  */
299  id_ctx->request_ctx = NULL;
300  id_ctx->retry_ctx = NULL;
301 }
302 
303 /** Cancel one packet.
304  *
305  * The packet can have a reply, or not. It doesn't matter.
306  *
307  * This also frees any IDs associated with the packet.
308  */
310 {
311  fr_radius_id_ctx_t *id_ctx;
312  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
313 
314  if (!my->retry) return 0;
315 
316  id_ctx = fr_radius_code_id_find(my->codes, packet->code, packet->id);
317  if (!id_ctx || !id_ctx->retry_ctx) return 0;
318 
319  fr_assert(id_ctx->packet == packet);
320 
321  if (fr_bio_retry_entry_cancel(my->retry, id_ctx->retry_ctx) < 0) return -1;
322 
323  id_ctx->retry_ctx = NULL;
324  id_ctx->packet = NULL;
325 
326  return 0;
327 }
328 
329 int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, void **request_ctx_p, fr_packet_t **packet_p,
330  UNUSED TALLOC_CTX *out_ctx, fr_pair_list_t *out)
331 {
332  ssize_t slen;
333  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
334  fr_packet_t *reply, *original;
335 
336  /*
337  * We don't need to set up response.socket for connected bios.
338  */
339  fr_packet_t response = {};
340 
341  /*
342  * We read the response packet ctx into our local structure. If we have a real response, we will
343  * swap to using the request context, and not the response context.
344  */
345  slen = fr_bio_read(my->common.bio, &response, &my->buffer, sizeof(my->buffer));
346  if (!slen) return 0;
347 
348  if (slen < 0) {
349  fr_assert(slen != fr_bio_error(IO_WOULD_BLOCK));
350  return slen;
351  }
352 
353  original = response.uctx;
354 
355  /*
356  * Allocate the new request data structure
357  */
358  reply = fr_packet_alloc(original, false);
359  if (!reply) return -1;
360 
361  /*
362  * This is for connected sockets.
363  */
364  reply->socket = my->reply_socket;
365  reply->timestamp = fr_time();
366 
367  reply->data = talloc_memdup(reply, my->buffer, slen);
368  if (!reply->data) {
369  talloc_free(reply);
370  return -1;
371  }
372  reply->data_len = slen;
373 
374  reply->code = reply->data[0];
375  reply->id = reply->data[1];
376  memcpy(reply->vector, reply->data + 4, sizeof(reply->vector));
377 
378  /*
379  * If this fails, we're out of memory.
380  */
381  if (fr_radius_decode_simple(original, out, reply->data, reply->data_len,
382  original->vector, (char const *) my->cfg.verify.secret) < 0) {
383  talloc_free(reply);
384  return -1;
385  }
386 
387  *request_ctx_p = original->uctx;
388  *packet_p = reply;
389 
390  return 1;
391 }
392 
394 {
395  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
396 
397  return my->fd;
398 }
399 
401 {
402  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
403 
404  return my->info.outstanding;
405 }
406 
408 {
409  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
410 
411  return &my->info;
412 }
413 
414 
416 {
417  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
418 
419  if (!code || (code >= FR_RADIUS_CODE_MAX)) {
420  fr_strerror_const("Invalid packet code");
421  return -1;
422  }
423 
424  if ((id < 0) || (id > 256)) {
425  fr_strerror_const("Invalid ID");
426  return -1;
427  }
428 
429  return fr_radius_code_id_force(my->codes, code, id);
430 }
431 
432 
433 /** Try to connect a socket.
434  *
435  * Calls fr_bio_fd_connect()
436  *
437  * @param bio the packet bio
438  * @return
439  * - 0 for "connected, can continue"
440  * - fr_bio_error(IO_WOULD_BLOCK) for "not yet connected, please try again"
441  * - <0 for other fr_bio_error()
442  *
443  */
445 {
446  int rcode;
447  fr_radius_client_fd_bio_t *my = talloc_get_type_abort(bio, fr_radius_client_fd_bio_t);
448 
449  if (my->info.connected) return 0;
450 
451  switch (my->fd_info->type) {
452  default:
453  fr_strerror_const("Invalid RADIUS client bio for connect");
454  return fr_bio_error(GENERIC);
455 
457  return 0;
458 
459  case FR_BIO_FD_CONNECTED:
460  break;
461  }
462 
463  switch(my->fd_info->state) {
465  fr_strerror_const("Invalid RADIUS client bio state");
466  return fr_bio_error(GENERIC);
467 
469  fr_strerror_const("RADIUS client bio is closed");
470  return fr_bio_error(GENERIC);
471 
473  return 0;
474 
476  break;
477  }
478 
479  /*
480  * Try to connect it.
481  */
482  rcode = fr_bio_fd_connect(my->fd);
483 
484  my->info.connected = (rcode == 0);
485  return rcode;
486 }
static int const char char buffer[256]
Definition: acutest.h:574
static ssize_t fr_bio_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Write raw data to a bio.
Definition: base.h:164
static ssize_t fr_bio_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read raw data from a bio.
Definition: base.h:141
void * uctx
user ctx, caller can manually set it.
Definition: base.h:104
#define fr_bio_error(_x)
Definition: base.h:184
Definition: base.h:103
fr_bio_t * bio
underlying bio for IO
Definition: packet.h:75
fr_bio_t * fr_bio_retry_alloc(TALLOC_CTX *ctx, size_t max_saved, fr_bio_retry_sent_t sent, fr_bio_retry_response_t response, fr_bio_retry_rewrite_t rewrite, fr_bio_retry_release_t release, fr_bio_retry_config_t const *cfg, fr_bio_t *next)
Allocate a fr_bio_retry_t.
Definition: retry.c:852
int fr_bio_retry_entry_start(UNUSED fr_bio_t *bio, fr_bio_retry_entry_t *item, fr_retry_config_t const *cfg)
Set a per-packet retry config.
Definition: retry.c:799
int fr_bio_retry_entry_cancel(fr_bio_t *bio, fr_bio_retry_entry_t *item)
Cancel one item.
Definition: retry.c:767
fr_bio_retry_release_reason_t
Definition: retry.h:54
void * packet_ctx
packet_ctx from the write() call
Definition: retry.c:44
fr_bio_retry_rewrite_t rewrite
per-packet rewrite callback
Definition: retry.c:45
void * uctx
user-writable context
Definition: retry.c:43
Definition: retry.c:42
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
fr_radius_code_id_t codes
Definition: client_priv.h:39
fr_bio_packet_t common
Definition: client_priv.h:35
fr_bio_fd_info_t const * fd_info
Definition: client_priv.h:41
fr_radius_client_config_t cfg
Definition: client_priv.h:37
fr_radius_client_bio_info_t info
Definition: client_priv.h:48
uint8_t buffer[4096]
temporary read buffer
Definition: client_priv.h:54
fr_bio_packet_t * fr_radius_client_tcp_bio_alloc(TALLOC_CTX *ctx, fr_radius_client_config_t *cfg, fr_bio_fd_config_t const *fd_cfg)
Allocate a RADIUS bio for writing client packets.
Definition: client_tcp.c:50
fr_bio_packet_t * fr_radius_client_udp_bio_alloc(TALLOC_CTX *ctx, fr_radius_client_config_t *cfg, fr_bio_fd_config_t const *fd_cfg)
Allocate a RADIUS bio for writing client packets.
Definition: client_udp.c:51
fr_radius_packet_code_t
RADIUS packet codes.
Definition: defs.h:31
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition: defs.h:43
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition: defs.h:33
@ FR_RADIUS_CODE_DISCONNECT_REQUEST
RFC3575/RFC5176 - Disconnect-Request.
Definition: defs.h:46
@ FR_RADIUS_CODE_MAX
Maximum possible protocol code.
Definition: defs.h:53
@ FR_RADIUS_CODE_DISCONNECT_ACK
RFC3575/RFC5176 - Disconnect-Ack (positive)
Definition: defs.h:47
@ FR_RADIUS_CODE_COA_REQUEST
RFC3575/RFC5176 - CoA-Request.
Definition: defs.h:49
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition: defs.h:34
@ FR_RADIUS_CODE_ACCOUNTING_RESPONSE
RFC2866 - Accounting-Response.
Definition: defs.h:37
@ FR_RADIUS_CODE_COA_NAK
RFC3575/RFC5176 - CoA-Nak (not willing to perform)
Definition: defs.h:51
@ FR_RADIUS_CODE_COA_ACK
RFC3575/RFC5176 - CoA-Ack (positive)
Definition: defs.h:50
@ FR_RADIUS_CODE_DISCONNECT_NAK
RFC3575/RFC5176 - Disconnect-Nak (not willing to perform)
Definition: defs.h:48
@ FR_RADIUS_CODE_PROTOCOL_ERROR
RFC7930 - Protocol-Error (generic NAK)
Definition: defs.h:52
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
Definition: defs.h:36
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
Definition: defs.h:35
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
Definition: fd.c:1167
fr_bio_t * fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_cb_funcs_t *cb, fr_bio_fd_config_t const *cfg, size_t offset)
Allocate a FD bio.
Definition: fd.c:1018
int fr_bio_fd_connect(fr_bio_t *bio)
Finalize a connect()
Definition: fd.c:1125
fr_socket_t socket
as connected socket
Definition: fd.h:108
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
Definition: fd.h:64
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition: fd.h:61
fr_bio_fd_type_t type
type of the socket
Definition: fd.h:110
fr_bio_fd_state_t state
connecting, open, closed, etc.
Definition: fd.h:112
@ FR_BIO_FD_STATE_CLOSED
Definition: fd.h:55
@ FR_BIO_FD_STATE_INVALID
Definition: fd.h:54
@ FR_BIO_FD_STATE_CONNECTING
Definition: fd.h:57
@ FR_BIO_FD_STATE_OPEN
error states must be before this
Definition: fd.h:56
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
Definition: fd.h:77
char const * path
for Unix domain sockets
Definition: fd.h:92
char const * filename
for files
Definition: fd.h:97
int socket_type
SOCK_STREAM or SOCK_DGRAM.
Definition: fd.h:79
Configuration for sockets.
Definition: fd.h:76
int fr_bio_free(fr_bio_t *bio)
Free this bio, and everything it calls.
Definition: base.c:113
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition: base.c:152
fr_bio_t * fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
Allocate a memory buffer bio.
Definition: mem.c:661
talloc_free(reap)
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition: packet.c:38
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
#define RADIUS_HEADER_LENGTH
Definition: net.h:80
int fr_radius_verify(uint8_t *packet, uint8_t const *vector, uint8_t const *secret, size_t secret_len, bool require_ma)
Verify a request / response packet.
Definition: base.c:719
ssize_t fr_radius_decode_simple(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len, uint8_t const *vector, char const *secret)
Simple wrapper for callers who just need a shared secret.
Definition: base.c:1097
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Definition: base.c:94
bool require_message_authenticator
Definition: bio.h:41
uint8_t const * secret
Definition: bio.h:34
size_t secret_len
Definition: bio.h:35
fr_radius_bio_verify_t verify
Definition: client.h:37
fr_bio_retry_config_t retry_cfg
Definition: client.h:39
fr_retry_config_t retry[FR_RADIUS_CODE_MAX]
default retry configuration for each packet type
Definition: client.h:43
bool outgoing[FR_RADIUS_CODE_MAX]
allowed outgoing packet types
Definition: client.h:41
fr_radius_id_t * fr_radius_id_alloc(TALLOC_CTX *ctx)
Allocate a tracking structure for one packet code.
Definition: id.c:45
static void fr_radius_code_id_push(fr_radius_code_id_t codes, fr_packet_t const *packet)
Definition: id.h:74
static fr_radius_id_ctx_t * fr_radius_code_id_pop(fr_radius_code_id_t codes, fr_packet_t *packet)
Definition: id.h:64
void * retry_ctx
to find the retry information
Definition: id.h:38
void * request_ctx
for the application to track
Definition: id.h:35
fr_packet_t * packet
outgoing packet
Definition: id.h:36
fr_packet_t * response
response to outgoing packet
Definition: id.h:37
static fr_radius_id_ctx_t * fr_radius_code_id_find(fr_radius_code_id_t codes, int code, int id)
Definition: id.h:84
static int fr_radius_code_id_force(fr_radius_code_id_t codes, int code, int id)
Definition: id.h:94
int fr_packet_sign(fr_packet_t *packet, fr_packet_t const *original, char const *secret)
Sign a previously encoded packet.
Definition: packet.c:160
ssize_t fr_packet_encode(fr_packet_t *packet, fr_pair_list_t *list, fr_packet_t const *original, char const *secret)
Encode a packet.
Definition: packet.c:52
static fr_bio_t * bio
Definition: radclient-ng.c:86
#define request_ctx
Talloc ctx for allocating request pairs under.
Definition: request.h:94
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)
Definition: client.c:61
static int _radius_client_fd_bio_free(fr_radius_client_fd_bio_t *my)
Definition: client.c:51
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)
Definition: client.c:284
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)
Definition: client.c:37
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_sent(fr_bio_t *bio, void *packet_ctx, const void *buffer, UNUSED size_t size, fr_bio_retry_entry_t *retry_ctx)
Definition: client.c:198
fr_bio_t * fr_radius_client_bio_get_fd(fr_bio_packet_t *bio)
Definition: client.c:393
static const fr_radius_packet_code_t allowed_replies[FR_RADIUS_CODE_MAX]
Definition: client.c:182
int fr_radius_client_fd_bio_read(fr_bio_packet_t *bio, void **request_ctx_p, fr_packet_t **packet_p, UNUSED TALLOC_CTX *out_ctx, fr_pair_list_t *out)
Definition: client.c:329
int fr_radius_client_fd_bio_cancel(fr_bio_packet_t *bio, fr_packet_t *packet)
Cancel one packet.
Definition: client.c:309
int fr_radius_client_bio_force_id(fr_bio_packet_t *bio, int code, int id)
Definition: client.c:415
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)
Definition: client.c:119
fr_radius_client_bio_info_t const * fr_radius_client_bio_info(fr_bio_packet_t *bio)
Definition: client.c:407
size_t fr_radius_client_bio_outstanding(fr_bio_packet_t *bio)
Definition: client.c:400
int fr_radius_client_bio_connect(fr_bio_packet_t *bio)
Try to connect a socket.
Definition: client.c:444
fr_assert(0)
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
void * uctx
Definition: packet.h:79
unsigned int code
Packet code (type).
Definition: packet.h:61
fr_socket_t socket
This packet was received on.
Definition: packet.h:57
int id
Packet ID (used to link requests/responses).
Definition: packet.h:60
uint8_t * data
Packet data (body).
Definition: packet.h:63
size_t data_len
Length of packet data.
Definition: packet.h:64
uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH]
RADIUS authentication vector.
Definition: packet.h:69
fr_time_t timestamp
When we received the packet.
Definition: packet.h:58
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition: socket.h:78
static void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
Swap src/dst information of a fr_socket_t.
Definition: socket.h:121
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984