The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
server_udp.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: f753e259b5d9826882fc06effa42bff7bdd8ca74 $
19  *
20  * @file protocols/radius/server_udp.c
21  * @brief Functions to support RADIUS bio handlers for server udp sockets
22  *
23  * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
24  */
25 RCSID("$Id: f753e259b5d9826882fc06effa42bff7bdd8ca74 $")
26 
27 #include <freeradius-devel/bio/packet.h>
28 #include <freeradius-devel/radius/server_udp.h>
29 #include <freeradius-devel/radius/server_priv.h>
30 
31 static bool radius_server_dedup_receive(fr_bio_t *bio, fr_bio_dedup_entry_t *dedup_ctx, void *packet_ctx)
32 {
33  fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_server_fd_bio_t);
35  fr_radius_server_bio_pctx_t *ctx = packet_ctx;
36 
37  /*
38  * Find any previous entry.
39  */
40  prev = fr_rb_find(&my->rb, dedup_ctx);
41  if (prev) {
42  // @todo - signal duplicate packet
43  return false;
44  }
45 
46  if (!fr_rb_insert(&my->rb, dedup_ctx)) {
47  // @todo - signal an error
48  return false;
49  }
50 
51  /*
52  * Glue it all together
53  */
54  dedup_ctx->uctx = ctx;
55  ctx->dedup = dedup_ctx;
56 
57  return true;
58 }
59 
61 {
62  fr_radius_server_bio_pctx_t *ctx = packet_ctx;
63 
64  return ctx->dedup;
65 }
66 
68 {
69  fr_radius_server_fd_bio_t *my = talloc_get_type_abort(bio->uctx, fr_radius_server_fd_bio_t);
70  fr_radius_server_bio_pctx_t *ctx = dedup_ctx->uctx;
71 
72  (void) fr_rb_delete(&my->rb, dedup_ctx);
73  ctx->dedup = NULL;
74 }
75 
76 static int fr_radius_server_udp_bio_read(fr_bio_packet_t *bio, void **packet_ctx_p, fr_packet_t **packet_p,
77  TALLOC_CTX *out_ctx, fr_pair_list_t *out)
78 {
79  int rcode;
81 
82  /*
83  * Read the packet.
84  */
85  rcode = fr_radius_server_fd_bio_read(bio, packet_ctx_p, packet_p, out_ctx, out);
86  if (rcode < 0) return rcode;
87 
88  ctx = *packet_ctx_p;
89 
90  /*
91  * The dedup_ctx starts off with the raw data in a buffer somewhere. That buffer will get
92  * over-written with a later packet. So be sure to update the dedup_ctx with the long-term
93  * version of the packet contents.
94  */
95  fr_assert(ctx->dedup->packet_size == (*packet_p)->data_len);
96 
97  ctx->dedup->packet = (*packet_p)->data;
98  ctx->dedup->packet_size = (*packet_p)->data_len;
99 
100  return 0;
101 }
102 
103 /** Allocate a RADIUS bio for receiving packets from clients.
104  *
105  * It also verifies that the packets we receive are valid for RADIUS.
106  */
108 {
110 
111  my = fr_radius_server_fd_bio_alloc(ctx, 2 * 4096, cfg, fd_cfg);
112  if (!my) return NULL;
113 
114  if (fr_bio_mem_set_verify(my->mem, fr_radius_bio_verify_datagram, &my->cfg.verify, true) < 0) {
115  fail:
116  talloc_free(my);
117  return NULL;
118  }
119 
120  /*
121  * Once we've allocated a FD and memory BIO, UDP needs de-duping.
122  */
125  if (!my->dedup) goto fail;
126  my->dedup->uctx = my;
127 
128  my->common.bio = my->dedup;
129 
130  my->common.read = fr_radius_server_udp_bio_read;
131  my->common.write = fr_radius_server_fd_bio_write;
132 
133  // @todo - insert comparison function
134  // @todo - comparison function is different for connected and unconnected sockets
135 
136  return (fr_bio_packet_t *) my;
137 }
void * uctx
user ctx, caller can manually set it.
Definition: base.h:113
Definition: base.h:112
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
fr_bio_t * fr_bio_dedup_alloc(TALLOC_CTX *ctx, size_t max_saved, fr_bio_dedup_receive_t receive, fr_bio_dedup_release_t release, fr_bio_dedup_get_item_t get_item, fr_bio_dedup_config_t const *cfg, fr_bio_t *next)
Allocate a fr_bio_dedup_t.
Definition: dedup.c:1035
void * uctx
user-writable context
Definition: dedup.c:96
size_t packet_size
size of the cached packet data
Definition: dedup.c:99
uint8_t * packet
cached packet data for finding duplicates
Definition: dedup.c:98
fr_bio_dedup_release_reason_t
Definition: dedup.h:58
Definition: dedup.c:95
Configuration for sockets.
Definition: fd.h:78
fr_bio_shutdown & my
Definition: fd_errno.h:59
int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, void *verify_ctx, bool datagram)
Set the verification function for memory bios.
Definition: mem.c:880
talloc_free(reap)
fr_bio_verify_action_t fr_radius_bio_verify_datagram(UNUSED fr_bio_t *bio, void *verify_ctx, UNUSED void *packet_ctx, const void *data, size_t *size)
And verify a datagram packet.
Definition: bio.c:64
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
int fr_radius_server_fd_bio_read(fr_bio_packet_t *bio, UNUSED void **packet_ctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out)
Definition: server.c:134
fr_radius_server_fd_bio_t * fr_radius_server_fd_bio_alloc(TALLOC_CTX *ctx, size_t read_size, fr_radius_server_config_t *cfg, fr_bio_fd_config_t const *fd_cfg)
Definition: server.c:58
int fr_radius_server_fd_bio_write(fr_bio_packet_t *bio, UNUSED void *pctx, fr_packet_t *reply, fr_pair_list_t *list)
Definition: server.c:100
fr_bio_dedup_entry_t * dedup
Definition: server.h:54
fr_bio_dedup_config_t dedup_cfg
Definition: server.h:39
static bool radius_server_dedup_receive(fr_bio_t *bio, fr_bio_dedup_entry_t *dedup_ctx, void *packet_ctx)
Definition: server_udp.c:31
static fr_bio_dedup_entry_t * radius_server_dedup_get_item(UNUSED fr_bio_t *bio, void *packet_ctx)
Definition: server_udp.c:60
fr_bio_packet_t * fr_radius_server_udp_bio_alloc(TALLOC_CTX *ctx, fr_radius_server_config_t *cfg, fr_bio_fd_config_t const *fd_cfg)
Allocate a RADIUS bio for receiving packets from clients.
Definition: server_udp.c:107
static void radius_server_dedup_release(fr_bio_t *bio, fr_bio_dedup_entry_t *dedup_ctx, UNUSED fr_bio_dedup_release_reason_t reason)
Definition: server_udp.c:67
static int fr_radius_server_udp_bio_read(fr_bio_packet_t *bio, void **packet_ctx_p, fr_packet_t **packet_p, TALLOC_CTX *out_ctx, fr_pair_list_t *out)
Definition: server_udp.c:76
fr_assert(0)
static size_t char ** out
Definition: value.h:997