24 RCSID(
"$Id: fc972abb18b9dcbdb4595c20d9d9870bae0b13fb $")
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>
65 typedef struct CC_HINT(__packed__) {
75 #define ICMP_ECHOREPLY (0)
76 #define ICMP_ECHOREQUEST (8)
78 #define ICMPV6_ECHOREQUEST (128)
79 #define ICMPV6_ECHOREPLY (129)
93 end =
data + data_len;
99 while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
120 vb->vb_bool =
echo->replied;
135 RDEBUG2(
"Cancelling ICMP request for %pV (counter=%d)",
echo->ip,
echo->counter);
146 if (
echo->replied)
return;
148 RDEBUG2(
"No response to ICMP request for %pV (counter=%d)",
echo->ip,
echo->counter);
178 struct sockaddr_storage dst;
187 RPEDEBUG(
"Failed casting result to IP address");
193 echo->request = request;
204 RPEDEBUG(
"Failed inserting IP into tracking table");
217 RDEBUG(
"Sending ICMP request to %pV (counter=%d)",
echo->ip,
echo->counter);
223 .counter =
echo->counter
246 rcode = sendto(t->
fd, &icmp,
sizeof(icmp), 0, (
struct sockaddr *) &dst, salen);
254 if ((
size_t) rcode <
sizeof(icmp)) {
255 REDEBUG(
"Failed sending entire ICMP packet");
264 static int8_t
echo_cmp(
void const *one,
void const *two)
286 if (len <= 0)
return;
305 if ((
IP_HL(ip) +
sizeof(*icmp)) >
sizeof(
buffer)) {
356 echo->replied =
true;
366 ERROR(
"%s - Failed reading from ICMP socket - Closing it", mctx->
mi->
name);
380 if (t->
fd < 0)
return 0;
406 memcpy(our_mctx, mctx,
sizeof(*our_mctx));
424 af =
inst->src_ipaddr.af;
434 proto = IPPROTO_ICMP;
442 proto = IPPROTO_ICMPV6;
459 fd = socket(af, SOCK_DGRAM,
proto);
460 if (fd < 0) fd = socket(af, SOCK_RAW,
proto);
470 #define FD_CLOEXEC (0)
473 (void) fcntl(fd, F_SETFL, O_NONBLOCK |
FD_CLOEXEC);
475 if (
inst->src_ipaddr.af != AF_UNSPEC) {
476 ipaddr =
inst->src_ipaddr;
531 # ifndef HAVE_CAPABILITY_H
532 if ((geteuid() != 0))
PWARN(
"Server not built with cap interface, opening raw sockets will likely fail");
537 if ((fr_cap_enable(CAP_NET_RAW, CAP_EFFECTIVE) < 0) && (geteuid() != 0)) {
538 PERROR(
"Failed setting capabilities required to open ICMP socket");
568 .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.
fr_dcursor_eval_t void const * uctx
static fr_time_delta_t timeout
#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.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
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.
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)
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)
#define fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black tree.
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)
The main red black tree structure.
static int mod_load(void)
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.
static int mod_instantiate(module_inst_ctx_t const *mctx)
uint32_t data
another 32-bits of randomness
uint32_t counter
for pinging the same IP multiple times
static int instantiate(module_inst_ctx_t const *mctx)
char const * name
Instance name e.g. user_database.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
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.