24 RCSID(
"$Id: 393b9b071b96aba948877f7a85f6039813dbe208 $")
26 #define LOG_PREFIX mctx->inst->name
28 #include <freeradius-devel/server/base.h>
29 #include <freeradius-devel/server/module_rlm.h>
30 #include <freeradius-devel/util/cap.h>
31 #include <freeradius-devel/util/debug.h>
32 #include <freeradius-devel/unlang/xlat_func.h>
67 typedef struct CC_HINT(__packed__) {
77 #define ICMP_ECHOREPLY (0)
78 #define ICMP_ECHOREQUEST (8)
80 #define ICMPV6_ECHOREQUEST (128)
81 #define ICMPV6_ECHOREPLY (129)
95 end =
data + data_len;
101 while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
122 vb->vb_bool =
echo->replied;
137 RDEBUG2(
"Cancelling ICMP request for %pV (counter=%d)",
echo->ip,
echo->counter);
148 if (
echo->replied)
return;
150 RDEBUG2(
"No response to ICMP request for %pV (counter=%d)",
echo->ip,
echo->counter);
180 struct sockaddr_storage dst;
189 RPEDEBUG(
"Failed casting result to IP address");
195 echo->request = request;
206 RPEDEBUG(
"Failed inserting IP into tracking table");
219 RDEBUG(
"Sending ICMP request to %pV (counter=%d)",
echo->ip,
echo->counter);
225 .counter =
echo->counter
248 rcode = sendto(t->
fd, &icmp,
sizeof(icmp), 0, (
struct sockaddr *) &dst, salen);
256 if ((
size_t) rcode <
sizeof(icmp)) {
257 REDEBUG(
"Failed sending entire ICMP packet");
266 static int8_t
echo_cmp(
void const *one,
void const *two)
288 if (len <= 0)
return;
307 if ((
IP_HL(ip) +
sizeof(*icmp)) >
sizeof(
buffer)) {
349 DEBUG(
"Can't find packet counter=%d in tree", icmp->
counter);
358 echo->replied =
true;
363 UNUSED int fd_errno,
void *uctx)
368 ERROR(
"Failed reading from ICMP socket - Closing it");
392 memcpy(our_mctx, mctx,
sizeof(*our_mctx));
410 af =
inst->src_ipaddr.af;
420 proto = IPPROTO_ICMP;
428 proto = IPPROTO_ICMPV6;
445 fd = socket(af, SOCK_DGRAM,
proto);
446 if (fd < 0) fd = socket(af, SOCK_RAW,
proto);
456 #define FD_CLOEXEC (0)
459 (void) fcntl(fd, F_SETFL, O_NONBLOCK |
FD_CLOEXEC);
461 if (
inst->src_ipaddr.af != AF_UNSPEC) {
462 ipaddr =
inst->src_ipaddr;
506 # ifndef HAVE_CAPABILITY_H
507 if ((geteuid() != 0))
PWARN(
"Server not built with cap interface, opening raw sockets will likely fail");
512 if ((fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE) < 0) && (geteuid() != 0)) {
513 PERROR(
"Failed setting capabilities required to open ICMP socket");
530 if (t->
fd < 0)
return 0;
558 .thread_inst_type =
"rlm_icmp_thread_t",
static int const char char buffer[256]
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#define CONF_PARSER_TERMINATOR
#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
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
#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
Defines a CONF_PAIR to C data type mapping.
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
static fr_time_delta_t timeout
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define fr_event_fd_insert(...)
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
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.
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.
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
#define RPEDEBUG(fmt,...)
#define HEXDUMP4(_data, _len, _fmt,...)
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.
Stores all information relating to an event list.
static bool echo
Main radmin state.
@ 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.
void * thread
Thread specific instance data.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
void * thread
Thread instance data.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
module_t common
Common fields presented by all modules.
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)
uint16_t fr_ip6_pesudo_header_checksum(struct in6_addr const *src, struct in6_addr const *dst, uint16_t ip_len, uint8_t ip_next)
fr_table_num_sorted_t const fr_net_ip_proto_table[]
Strings for L4 protocols.
fr_table_num_sorted_t const fr_net_af_table[]
Strings for address families.
static const conf_parser_t config[]
static char const * proto(int id, int porttype)
uint32_t fr_rand(void)
Return a 32-bit random number.
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
Return how many nodes there are in a tree.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
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.
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
The main red black tree structure.
request_t * request
so it can be resumed when we get the echo reply
fr_value_box_t * ip
the IP we're pinging
static void mod_icmp_error(fr_event_list_t *el, UNUSED int sockfd, UNUSED int flags, UNUSED int fd_errno, void *uctx)
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)
static void _xlat_icmp_timeout(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_time_t fired)
uint32_t counter
so that requests for the same IP are unique
static void xlat_icmp_cancel(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static uint16_t icmp_checksum(uint8_t *data, size_t data_len, uint16_t checksum)
static void mod_icmp_read(UNUSED fr_event_list_t *el, UNUSED int sockfd, UNUSED int flags, void *uctx)
static xlat_arg_parser_t const xlat_icmp_args[]
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Instantiate thread data for the submodule.
static int8_t echo_cmp(void const *one, void const *two)
fr_rb_node_t node
Entry in the outstanding list of echo requests.
static const conf_parser_t module_config[]
bool replied
do we have a reply?
#define ICMPV6_ECHOREQUEST
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Destroy thread data for the submodule.
uint32_t data
another 32-bits of randomness
uint32_t counter
for pinging the same IP multiple times
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
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.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
#define fr_time()
Allow us to arbitrarily manipulate time.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_add(_a, _b)
Add a time/time delta together.
A time delta, a difference in time measured in nanoseconds.
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.
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.
bool required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const_push(_msg)
#define fr_strerror_const(_msg)
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.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
static size_t char ** out
void * rctx
Resume context.
module_ctx_t const * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.