The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_icmp.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program 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
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; 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: deff545a7764828971a1a07bc00a58e335226ee5 $
19 * @file rlm_icmp.c
20 * @brief Send ICMP echo requests.
21 *
22 * @copyright 2020 Network RADIUS SAS (legal@networkradius.com)
23 */
24RCSID("$Id: deff545a7764828971a1a07bc00a58e335226ee5 $")
25
26#include <freeradius-devel/server/base.h>
27#include <freeradius-devel/server/module_rlm.h>
28#include <freeradius-devel/util/cap.h>
29#include <freeradius-devel/util/debug.h>
30#include <freeradius-devel/unlang/xlat_func.h>
31
32#include <fcntl.h>
33
34/*
35 * Define a structure for our module configuration.
36 */
42
55
56typedef struct {
57 fr_rb_node_t node; //!< Entry in the outstanding list of echo requests.
58 bool replied; //!< do we have a reply?
59 fr_value_box_t *ip; //!< the IP we're pinging
60 uint32_t counter; //!< for pinging the same IP multiple times
61 request_t *request; //!< so it can be resumed when we get the echo reply
63
64typedef struct CC_HINT(__packed__) {
70 uint32_t data; //!< another 32-bits of randomness
71 uint32_t counter; //!< so that requests for the same IP are unique
73
74#define ICMP_ECHOREPLY (0)
75#define ICMP_ECHOREQUEST (8)
76
77#define ICMPV6_ECHOREQUEST (128)
78#define ICMPV6_ECHOREPLY (129)
79
80/*
81 * Calculate the ICMP portion of the checksum
82 */
83static uint16_t icmp_checksum(uint8_t *data, size_t data_len, uint16_t checksum)
84{
85 uint8_t *p, *end;
86 uint64_t sum;
87
88 sum = checksum;
89 data_len &= ~((size_t) 1); /* ensure it's always 16-bit aligned */
90
91 p = data;
92 end = data + data_len;
93 while (p < end) {
94 sum += fr_nbo_to_uint16(p); /* type / code */
95 p += 2;
96 }
97
98 while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
99
100 return ((uint16_t) ~sum);
101}
102
103static const conf_parser_t module_config[] = {
104 { FR_CONF_OFFSET("interface", rlm_icmp_t, interface) },
105 { FR_CONF_OFFSET_TYPE_FLAGS("src_ipaddr", FR_TYPE_COMBO_IP_ADDR, 0, rlm_icmp_t, src_ipaddr) },
106 { FR_CONF_OFFSET("timeout", rlm_icmp_t, timeout), .dflt = "1s" },
108};
109
111 xlat_ctx_t const *xctx,
112 UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
113{
114 rlm_icmp_echo_t *echo = talloc_get_type_abort(xctx->rctx, rlm_icmp_echo_t);
115 rlm_icmp_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, rlm_icmp_thread_t);
116 fr_value_box_t *vb;
117
118 MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL));
119 vb->vb_bool = echo->replied;
120
121 (void) fr_rb_delete(t->tree, echo);
122 talloc_free(echo);
123
125
126 return XLAT_ACTION_DONE;
127}
128
129static void xlat_icmp_cancel(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
130{
131 rlm_icmp_echo_t *echo = talloc_get_type_abort(xctx->rctx, rlm_icmp_echo_t);
132 rlm_icmp_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, rlm_icmp_thread_t);
133
134 RDEBUG2("Cancelling ICMP request for %pV (counter=%d)", echo->ip, echo->counter);
135
136 (void) fr_rb_delete(t->tree, echo);
137 talloc_free(echo);
138}
139
140
141static void _xlat_icmp_timeout(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_time_t fired)
142{
143 rlm_icmp_echo_t *echo = talloc_get_type_abort(xctx->rctx, rlm_icmp_echo_t);
144
145 if (echo->replied) return; /* it MUST already have been marked resumable. */
146
147 RDEBUG2("No response to ICMP request for %pV (counter=%d)", echo->ip, echo->counter);
148
150}
151
153 { .required = true, .single = true, .type = FR_TYPE_STRING },
155};
156
157/** Xlat to ping a specified ip address
158 *
159 * Example (ping 192.0.2.1):
160@verbatim
161%icmp(192.0.2.1)
162@endverbatim
163 *
164 * @ingroup xlat_functions
165 */
167 xlat_ctx_t const *xctx,
168 request_t *request, fr_value_box_list_t *in)
169{
170 rlm_icmp_t *inst = talloc_get_type_abort(xctx->mctx->mi->data, rlm_icmp_t);
171 rlm_icmp_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, rlm_icmp_thread_t);
172 rlm_icmp_echo_t *echo;
173 icmp_header_t icmp;
174 uint16_t checksum;
175 ssize_t rcode;
176 socklen_t salen;
177 struct sockaddr_storage dst;
178 fr_value_box_t *in_head = fr_value_box_list_head(in);
179
180 /*
181 * If there's no input, do we can't ping anything.
182 */
183 if (!in_head) return XLAT_ACTION_FAIL;
184
185 if (fr_value_box_cast_in_place(ctx, in_head, t->ipaddr_type, NULL) < 0) {
186 RPEDEBUG("Failed casting result to IP address");
187 return XLAT_ACTION_FAIL;
188 }
189
190 MEM(echo = talloc_zero(ctx, rlm_icmp_echo_t));
191 echo->ip = in_head;
192 echo->request = request;
193 echo->counter = t->counter++;
194
195 /*
196 * Add the IP to the local tracking heap, so that the IO
197 * functions can find it.
198 *
199 * This insert will never fail, because of the unique
200 * counter above.
201 */
202 if (!fr_rb_insert(t->tree, echo)) {
203 RPEDEBUG("Failed inserting IP into tracking table");
204 talloc_free(echo);
205 return XLAT_ACTION_FAIL;
206 }
207
209 fr_time_add(fr_time(), inst->timeout)) < 0) {
210 RPEDEBUG("Failed adding timeout");
211 (void) fr_rb_delete(t->tree, echo);
212 talloc_free(echo);
213 return XLAT_ACTION_FAIL;
214 }
215
216 RDEBUG("Sending ICMP request to %pV (counter=%d)", echo->ip, echo->counter);
217
218 icmp = (icmp_header_t) {
219 .type = t->request_type,
220 .ident = t->ident,
221 .data = t->data,
222 .counter = echo->counter
223 };
224
225 (void) fr_ipaddr_to_sockaddr(&dst, &salen, &echo->ip->vb_ip, 0);
226
227 /*
228 * Calculate the checksum
229 */
230 checksum = 0;
231
232 /*
233 * Start off with the IPv6 pseudo-header checksum
234 */
235 if (t->ipaddr_type == FR_TYPE_IPV6_ADDR) {
236 checksum = fr_ip6_pseudo_header_checksum(&inst->src_ipaddr.addr.v6, &echo->ip->vb_ip.addr.v6,
237 sizeof(ip_header6_t) + sizeof(icmp), IPPROTO_ICMPV6);
238 }
239
240 /*
241 * Followed by checksumming the actual ICMP packet.
242 */
243 icmp.checksum = htons(icmp_checksum((uint8_t *) &icmp, sizeof(icmp), checksum));
244
245 rcode = sendto(t->fd, &icmp, sizeof(icmp), 0, (struct sockaddr *) &dst, salen);
246 if (rcode < 0) {
247 REDEBUG("Failed sending ICMP request to %pV: %s", echo->ip, fr_syserror(errno));
248 (void) fr_rb_delete(t->tree, echo);
249 talloc_free(echo);
250 return XLAT_ACTION_FAIL;
251 }
252
253 if ((size_t) rcode < sizeof(icmp)) {
254 REDEBUG("Failed sending entire ICMP packet");
255 (void) fr_rb_delete(t->tree, echo);
256 talloc_free(echo);
257 return XLAT_ACTION_FAIL;
258 }
259
261}
262
263static int8_t echo_cmp(void const *one, void const *two)
264{
265 rlm_icmp_echo_t const *a = one;
266 rlm_icmp_echo_t const *b = two;
267
268 /*
269 * No need to check IP, because "counter" is unique for each packet.
270 */
271 return CMP(a->counter, b->counter);
272}
273
274static void mod_icmp_read(UNUSED fr_event_list_t *el, UNUSED int sockfd, UNUSED int flags, void *uctx)
275{
276 module_thread_inst_ctx_t const *mctx = talloc_get_type_abort(uctx, module_thread_inst_ctx_t);
277 rlm_icmp_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_icmp_thread_t);
278
279 ssize_t len;
280 icmp_header_t *icmp;
281 rlm_icmp_echo_t my_echo, *echo;
282 uint64_t buffer[256];
283
284 len = read(t->fd, (char *) buffer, sizeof(buffer));
285 if (len <= 0) return;
286
287 HEXDUMP4((uint8_t const *)buffer, len, "received icmp packet ");
288
289 /*
290 * Ignore packets if we haven't sent any requests.
291 */
292 if (fr_rb_num_elements(t->tree) == 0) {
293 return;
294 }
295
296 // buffer is actually the IP header + the ICMP packet
297 if (t->ipaddr_type == FR_TYPE_IPV4_ADDR) {
299
300 if (IP_V(ip) != 4) {
301 return;
302 }
303
304 if ((IP_HL(ip) + sizeof(*icmp)) > sizeof(buffer)) {
305 return;
306 }
307
308 icmp = (icmp_header_t *) (((uint8_t *) buffer) + IP_HL(ip));
309 } else if (t->ipaddr_type == FR_TYPE_IPV6_ADDR) {
310 /*
311 * Outgoing packets automatically have an IPv6 header prepended to them
312 * (based on the destination address). ICMPv6 pseudo header checksum field
313 * (icmp6_cksum) will be filled automatically by the kernel. Incoming packets
314 * are received without the IPv6 header nor IPv6 extension headers.
315 *
316 * Note that this behavior is opposite from IPv4
317 * raw sockets and ICMPv4 sockets.
318 *
319 * Therefore, we don't have ip6 headers here. Only the icmp6 packet.
320 */
321 icmp = (icmp_header_t *) (((uint8_t *) buffer));
322 } else {
323 /*
324 * No idea. Ignore it.
325 */
326 return;
327 }
328
329 /*
330 * Ignore packets which aren't an echo reply, or which
331 * weren't for us. This is done *before* looking packets
332 * up in the rbtree, as these checks ensure that the
333 * packet is for this specific thread.
334 */
335 if ((icmp->type != t->reply_type) ||
336 (icmp->ident != t->ident) || (icmp->data != t->data)) {
337 return;
338 }
339
340 /*
341 * Look up the packet by the fields which determine *our* ICMP packets.
342 */
343 my_echo.counter = icmp->counter;
344 echo = fr_rb_find(t->tree, &my_echo);
345 if (!echo) {
346 DEBUG("%s - Can't find packet counter=%d in tree", mctx->mi->name, icmp->counter);
347 return;
348 }
349
350 (void) fr_rb_delete(t->tree, echo);
351
352 /*
353 * We have a reply!
354 */
355 echo->replied = true;
357}
358
360 UNUSED int fd_errno, void *uctx)
361{
362 module_thread_inst_ctx_t const *mctx = talloc_get_type_abort(uctx, module_thread_inst_ctx_t);
363 rlm_icmp_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_icmp_thread_t);
364
365 ERROR("%s - Failed reading from ICMP socket - Closing it", mctx->mi->name);
366
368 close(t->fd);
369 t->fd = -1;
370}
371
372/** Destroy thread data for the submodule.
373 *
374 */
376{
377 rlm_icmp_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_icmp_thread_t);
378
379 if (t->fd < 0) return 0;
380
381 (void) fr_event_fd_delete(mctx->el, t->fd, FR_EVENT_FILTER_IO);
382 close(t->fd);
383 t->fd = -1;
384
385 return 0;
386}
387
388/** Instantiate thread data for the submodule.
389 *
390 */
392{
393 module_thread_inst_ctx_t *our_mctx;
394 rlm_icmp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_icmp_t);
395 rlm_icmp_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_icmp_thread_t);
396 fr_ipaddr_t ipaddr, *src;
397
398 int fd, af, proto;
399
400 /*
401 * Create a copy of the mctx on the heap that we can
402 * pass as the uctx to the io functions.
403 */
404 MEM(our_mctx = talloc_zero(t, module_thread_inst_ctx_t));
405 memcpy(our_mctx, mctx, sizeof(*our_mctx));
406
407 MEM(t->tree = fr_rb_inline_alloc(t, rlm_icmp_echo_t, node, echo_cmp, NULL));
408
409 /*
410 * Since these fields are random numbers, we don't care
411 * about network / host byte order. No one other than us
412 * will be interpreting these fields. As such, we can
413 * just treat them as host byte order.
414 *
415 * The only side effect of this choice is that this code
416 * will use (e.g.) 0xabcd for the ident, and Wireshark,
417 * tcpdump, etc. may show the ident as 0xcdab. That's
418 * fine.
419 */
420 t->data = fr_rand();
421 t->ident = fr_rand();
422
423 af = inst->src_ipaddr.af;
424
425 switch (af) {
426 default:
427 fr_strerror_const("Unsupported address family");
428 return -1;
429
430 case AF_UNSPEC:
431 case AF_INET:
432 af = AF_INET;
433 proto = IPPROTO_ICMP;
437 break;
438
439 case AF_INET6:
440 af = AF_INET6;
441 proto = IPPROTO_ICMPV6;
445 break;
446 }
447
448 /*
449 * Try and open with SOCK_DGRAM.
450 * If we get permission denied, fall back to SOCK_RAW.
451 * For some reason with docker, even if we have all
452 * the capabilities opening a SOCK_DGRAM/IPPROTO_ICMP
453 * socket fails.
454 *
455 * We don't appear to need to specify the IP header
456 * and the xlat works fine. Very strange.
457 */
458 fd = socket(af, SOCK_DGRAM, proto);
459 if (fd < 0) fd = socket(af, SOCK_RAW, proto);
460 if (fd < 0) {
461 fr_strerror_printf("Failed opening socket (%s, %s): %s",
462 fr_table_str_by_value(fr_net_af_table, af, "<INVALID>"),
463 fr_table_str_by_value(fr_net_ip_proto_table, proto, "<INVALID>"),
464 fr_syserror(errno));
465 return -1;
466 }
467
468 if (fr_cloexec(fd) < 0) {
469 close(fd);
470 return -1;
471 }
472
473 if (inst->src_ipaddr.af != AF_UNSPEC) {
474 ipaddr = inst->src_ipaddr;
475 src = &ipaddr;
476 } else {
477 src = NULL;
478 }
479
480 /*
481 * Only bind if we have a src and interface.
482 */
483 if (src && inst->interface && (fr_socket_bind(fd, inst->interface, src, NULL) < 0)) {
484 close(fd);
485 return -1;
486 }
487
488 /*
489 * We assume that the outbound socket is always writable.
490 * If not, too bad. Packets will get lost.
491 */
492 if (fr_event_fd_insert(t, NULL, mctx->el, fd,
494 NULL,
496 our_mctx) < 0) {
497 fr_strerror_const_push("Failed adding socket to event loop");
498 close(fd);
499 return -1;
500 }
501 t->fd = fd;
502
503 return 0;
504}
505
506static int mod_instantiate(module_inst_ctx_t const *mctx)
507{
508 rlm_icmp_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_icmp_t);
509
510 FR_TIME_DELTA_BOUND_CHECK("timeout", inst->timeout, >=, fr_time_delta_from_msec(100)); /* 1/10s minimum timeout */
511 FR_TIME_DELTA_BOUND_CHECK("timeout", inst->timeout, <=, fr_time_delta_from_sec(10));
512
513 return 0;
514}
515
516static int mod_bootstrap(module_inst_ctx_t const *mctx)
517{
518 xlat_t *xlat;
519
520 xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, NULL, xlat_icmp, FR_TYPE_BOOL);
522
523 return 0;
524}
525
526static int mod_load(void)
527{
528#ifdef __linux__
529# ifndef HAVE_CAPABILITY_H
530 if ((geteuid() != 0)) PWARN("Server not built with cap interface, opening raw sockets will likely fail");
531# else
532 /*
533 * Request RAW capabilities on Linux. On other systems this does nothing.
534 */
535 if ((fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE) < 0) && (geteuid() != 0)) {
536 PERROR("Failed setting capabilities required to open ICMP socket");
537 return -1;
538 }
539# endif
540#endif
541
542 return 0;
543}
544
545
546/*
547 * The module name should be the only globally exported symbol.
548 * That is, everything else should be 'static'.
549 *
550 * If the module needs to temporarily modify it's instantiation
551 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
552 * The server will then take care of ensuring that the module
553 * is single-threaded.
554 */
557 .common = {
558 .magic = MODULE_MAGIC_INIT,
559 .name = "icmp",
560 .inst_size = sizeof(rlm_icmp_t),
562 .onload = mod_load,
563 .bootstrap = mod_bootstrap,
564 .instantiate = mod_instantiate,
565 .thread_inst_size = sizeof(rlm_icmp_thread_t),
566 .thread_inst_type = "rlm_icmp_thread_t",
567 .thread_instantiate = mod_thread_instantiate,
568 .thread_detach = mod_thread_detach
569 }
570};
static int const char char buffer[256]
Definition acutest.h:576
#define RCSID(id)
Definition build.h:506
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:113
#define UNUSED
Definition build.h:336
#define CAP_EFFECTIVE
Definition cap.h:48
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:657
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:280
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:528
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:238
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:594
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
Definition dcursor.h:435
#define MEM(x)
Definition debug.h:46
#define ERROR(fmt,...)
Definition dhcpclient.c:40
static int sockfd
Definition dhcpclient.c:55
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
static fr_slen_t in
Definition dict.h:882
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
#define fr_event_fd_insert(...)
Definition event.h:247
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
static xlat_action_t xlat_icmp(TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Xlat to ping a specified ip address.
Definition rlm_icmp.c:166
talloc_free(hp)
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
Definition inet.c:1399
IPv4/6 prefix.
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
Definition interpret.c:1636
#define PERROR(_fmt,...)
Definition log.h:228
#define PWARN(_fmt,...)
Definition log.h:227
#define RPEDEBUG(fmt,...)
Definition log.h:388
#define HEXDUMP4(_data, _len, _fmt,...)
Definition log.h:736
#define fr_time()
Definition event.c:60
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition event.c:1203
Stores all information relating to an event list.
Definition event.c:377
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition master.c:2873
unsigned short uint16_t
fr_type_t
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
unsigned long int size_t
int fr_cloexec(UNUSED int fd)
Definition misc.c:331
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * thread
Thread specific instance data.
Definition module_ctx.h:43
fr_event_list_t * el
Event list to register any IO handlers and timers against.
Definition module_ctx.h:68
void * thread
Thread instance data.
Definition module_ctx.h:67
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:64
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
Temporary structure to hold arguments for thread_instantiation calls.
Definition module_ctx.h:63
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Definition module_rlm.c:247
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition nbo.h:146
fr_table_num_sorted_t const fr_net_ip_proto_table[]
Strings for L4 protocols.
Definition net.c:28
uint16_t fr_ip6_pseudo_header_checksum(struct in6_addr const *src, struct in6_addr const *dst, uint16_t ip_len, uint8_t ip_next)
Definition net.c:169
fr_table_num_sorted_t const fr_net_af_table[]
Strings for address families.
Definition net.c:48
#define IP_HL(ip)
Definition net.h:93
#define IP_V(ip)
Definition net.h:92
static const conf_parser_t config[]
Definition base.c:163
static int mod_load(void)
Definition proto_arp.c:236
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
#define RDEBUG(fmt,...)
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:104
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
Return how many nodes there are in a tree.
Definition rb.c:781
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:577
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:626
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
Definition rb.c:741
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
Definition rb.h:269
The main red black tree structure.
Definition rb.h:71
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_always.c:172
static const conf_parser_t module_config[]
Definition rlm_always.c:58
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_load(void)
Definition rlm_icmp.c:526
request_t * request
so it can be resumed when we get the echo reply
Definition rlm_icmp.c:61
uint32_t data
Definition rlm_icmp.c:47
fr_value_box_t * ip
the IP we're pinging
Definition rlm_icmp.c:59
fr_ipaddr_t src_ipaddr
Definition rlm_icmp.c:40
static void mod_icmp_error(fr_event_list_t *el, UNUSED int sockfd, UNUSED int flags, UNUSED int fd_errno, void *uctx)
Definition rlm_icmp.c:359
static xlat_action_t xlat_icmp_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
Definition rlm_icmp.c:110
uint16_t ident
Definition rlm_icmp.c:48
module_rlm_t rlm_icmp
Definition rlm_icmp.c:556
uint8_t code
Definition rlm_icmp.c:66
static void _xlat_icmp_timeout(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_time_t fired)
Definition rlm_icmp.c:141
uint32_t counter
so that requests for the same IP are unique
Definition rlm_icmp.c:71
uint16_t sequence
Definition rlm_icmp.c:69
#define ICMP_ECHOREQUEST
Definition rlm_icmp.c:75
static void xlat_icmp_cancel(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
Definition rlm_icmp.c:129
uint16_t ident
Definition rlm_icmp.c:68
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition rlm_icmp.c:516
static uint16_t icmp_checksum(uint8_t *data, size_t data_len, uint16_t checksum)
Definition rlm_icmp.c:83
fr_time_delta_t timeout
Definition rlm_icmp.c:39
static void mod_icmp_read(UNUSED fr_event_list_t *el, UNUSED int sockfd, UNUSED int flags, void *uctx)
Definition rlm_icmp.c:274
#define ICMP_ECHOREPLY
Definition rlm_icmp.c:74
fr_type_t ipaddr_type
Definition rlm_icmp.c:51
static xlat_arg_parser_t const xlat_icmp_args[]
Definition rlm_icmp.c:152
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Instantiate thread data for the submodule.
Definition rlm_icmp.c:391
uint8_t request_type
Definition rlm_icmp.c:52
static int8_t echo_cmp(void const *one, void const *two)
Definition rlm_icmp.c:263
uint8_t reply_type
Definition rlm_icmp.c:53
fr_rb_tree_t * tree
Definition rlm_icmp.c:44
fr_rb_node_t node
Entry in the outstanding list of echo requests.
Definition rlm_icmp.c:57
static const conf_parser_t module_config[]
Definition rlm_icmp.c:103
uint8_t type
Definition rlm_icmp.c:65
char const * interface
Definition rlm_icmp.c:38
bool replied
do we have a reply?
Definition rlm_icmp.c:58
uint32_t counter
Definition rlm_icmp.c:49
#define ICMPV6_ECHOREPLY
Definition rlm_icmp.c:78
#define ICMPV6_ECHOREQUEST
Definition rlm_icmp.c:77
uint16_t checksum
Definition rlm_icmp.c:67
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Destroy thread data for the submodule.
Definition rlm_icmp.c:375
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition rlm_icmp.c:506
uint32_t data
another 32-bits of randomness
Definition rlm_icmp.c:70
uint32_t counter
for pinging the same IP multiple times
Definition rlm_icmp.c:60
char const * name
Instance name e.g. user_database.
Definition module.h:357
size_t inst_size
Size of the module's instance data.
Definition module.h:212
void * data
Module's instance data.
Definition module.h:293
void * boot
Data allocated during the boostrap phase.
Definition module.h:296
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface.
Definition socket.c:200
eap_aka_sim_process_conf_t * inst
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:772
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
Definition time.h:575
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_add(_a, _b)
Add a time/time delta together.
Definition time.h:196
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
static fr_event_list_t * el
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition xlat.c:543
int unlang_xlat_timeout_add(request_t *request, fr_unlang_xlat_timeout_t callback, void const *rctx, fr_time_t when)
Add a timeout for an xlat handler.
Definition xlat.c:150
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumed by an xlat function.
Definition xlat.h:145
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
#define fr_strerror_const(_msg)
Definition strerror.h:223
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
Definition value.c:4181
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:644
static fr_slen_t data
Definition value.h:1340
static size_t char ** out
Definition value.h:1030
void * rctx
Resume context.
Definition xlat_ctx.h:54
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition xlat_ctx.h:52
An xlat calling ctx.
Definition xlat_ctx.h:49
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:363