97 #include <netinet/ip.h>
98 #include <netinet/tcp.h>
99 #include <netinet/udp.h>
100 #include <netinet/ip6.h>
103 #define GENERIC_VENDOR_ID 0x0000
106 #define ASTERISK_VENDOR_ID 0x0004
166 #define INITIALIZE_GENERIC_HEP_IDS(hep_chunk, type) do { \
167 (hep_chunk)->vendor_id = htons(GENERIC_VENDOR_ID); \
168 (hep_chunk)->type_id = htons((type)); \
171 #define INITIALIZE_GENERIC_HEP_IDS_VAR(hep_chunk, type, len) do { \
172 INITIALIZE_GENERIC_HEP_IDS((hep_chunk), (type)); \
173 (hep_chunk)->length = htons(sizeof(*(hep_chunk)) + len); \
176 #define INITIALIZE_GENERIC_HEP_CHUNK(hep_item, type) do { \
177 INITIALIZE_GENERIC_HEP_IDS(&(hep_item)->chunk, (type)); \
178 (hep_item)->chunk.length = htons(sizeof(*(hep_item))); \
181 #define INITIALIZE_GENERIC_HEP_CHUNK_DATA(hep_item, type, value) do { \
182 INITIALIZE_GENERIC_HEP_CHUNK((hep_item), (type)); \
183 (hep_item)->data = (value); \
195 } __attribute__((packed));
200 } __attribute__((packed));
205 } __attribute__((packed));
210 } __attribute__((packed));
215 } __attribute__((packed));
219 struct in6_addr data;
220 } __attribute__((packed));
225 } __attribute__((packed));
239 } __attribute__((packed));
269 .category =
"general",
293 .files = ACO_FILES(&hepv3_conf),
298 static void hepv3_config_dtor(
void *obj)
310 config = ao2_alloc(
sizeof(*config), hepv3_config_dtor);
352 if (strcasecmp(var->
name,
"uuid_type")) {
356 if (!strcasecmp(var->
value,
"channel")) {
357 global_config->
uuid_type = HEP_UUID_TYPE_CHANNEL;
358 }
else if (!strcasecmp(var->
value,
"call-id")) {
359 global_config->
uuid_type = HEP_UUID_TYPE_CALL_ID;
390 ast_log(AST_LOG_WARNING,
"Failed to create address from %s\n", config->
capture_address);
398 ast_log(AST_LOG_WARNING,
"Failed to create socket for address %s: %s\n",
412 ast_free(info->
uuid);
422 return HEP_UUID_TYPE_CALL_ID;
425 return config->general->uuid_type;
432 return config && config->general->enabled;
449 memcpy(info->
payload, payload, len);
465 unsigned int packet_len = 0, sock_buffer_len;
468 struct hep_chunk auth_key, payload, uuid, capturename;
472 if (!capture_info || !config || !hepv3_data) {
477 ast_log(AST_LOG_NOTICE,
"Unable to send packet: Address Family mismatch between source/destination\n");
481 packet_len =
sizeof(hg_pkt);
484 memcpy(hg_pkt.header.id,
"\x48\x45\x50\x33", 4);
489 INITIALIZE_GENERIC_HEP_CHUNK_DATA(&hg_pkt.time_sec,
CHUNK_TYPE_TIMESTAMP_SEC, htonl(capture_info->capture_time.tv_sec));
490 INITIALIZE_GENERIC_HEP_CHUNK_DATA(&hg_pkt.time_usec,
CHUNK_TYPE_TIMESTAMP_USEC, htonl(capture_info->capture_time.tv_usec));
495 INITIALIZE_GENERIC_HEP_CHUNK_DATA(&hg_pkt.ip_family,
504 packet_len += (
sizeof(ipv4_src) +
sizeof(ipv4_dst));
506 INITIALIZE_GENERIC_HEP_CHUNK_DATA(&hg_pkt.ip_family,
515 packet_len += (
sizeof(ipv6_src) +
sizeof(ipv6_dst));
518 if (!ast_strlen_zero(config->general->capture_password)) {
519 INITIALIZE_GENERIC_HEP_IDS_VAR(&auth_key,
CHUNK_TYPE_AUTH_KEY, strlen(config->general->capture_password));
520 packet_len += (
sizeof(auth_key) + strlen(config->general->capture_password));
522 if (!ast_strlen_zero(config->general->capture_name)) {
524 packet_len += (
sizeof(capturename) + strlen(config->general->capture_name));
526 INITIALIZE_GENERIC_HEP_IDS_VAR(&uuid,
CHUNK_TYPE_UUID, strlen(capture_info->uuid));
527 packet_len += (
sizeof(uuid) + strlen(capture_info->uuid));
528 INITIALIZE_GENERIC_HEP_IDS_VAR(&payload,
530 packet_len += (
sizeof(payload) + capture_info->len);
531 hg_pkt.header.length = htons(packet_len);
540 memcpy(sock_buffer, &hg_pkt,
sizeof(hg_pkt));
541 sock_buffer_len =
sizeof(hg_pkt);
545 memcpy(sock_buffer + sock_buffer_len, &ipv4_src,
sizeof(ipv4_src));
546 sock_buffer_len +=
sizeof(ipv4_src);
547 memcpy(sock_buffer + sock_buffer_len, &ipv4_dst,
sizeof(ipv4_dst));
548 sock_buffer_len +=
sizeof(ipv4_dst);
550 memcpy(sock_buffer + sock_buffer_len, &ipv6_src,
sizeof(ipv6_src));
551 sock_buffer_len +=
sizeof(ipv6_src);
552 memcpy(sock_buffer + sock_buffer_len, &ipv6_dst,
sizeof(ipv6_dst));
553 sock_buffer_len +=
sizeof(ipv6_dst);
557 if (!ast_strlen_zero(config->general->capture_password)) {
558 memcpy(sock_buffer + sock_buffer_len, &auth_key,
sizeof(auth_key));
559 sock_buffer_len +=
sizeof(auth_key);
560 memcpy(sock_buffer + sock_buffer_len, config->general->capture_password, strlen(config->general->capture_password));
561 sock_buffer_len += strlen(config->general->capture_password);
565 memcpy(sock_buffer + sock_buffer_len, &uuid,
sizeof(uuid));
566 sock_buffer_len +=
sizeof(uuid);
567 memcpy(sock_buffer + sock_buffer_len, capture_info->uuid, strlen(capture_info->uuid));
568 sock_buffer_len += strlen(capture_info->uuid);
571 if (!ast_strlen_zero(config->general->capture_name)) {
572 memcpy(sock_buffer + sock_buffer_len, &capturename,
sizeof(capturename));
573 sock_buffer_len +=
sizeof(capturename);
574 memcpy(sock_buffer + sock_buffer_len, config->general->capture_name, strlen(config->general->capture_name));
575 sock_buffer_len += strlen(config->general->capture_name);
579 memcpy(sock_buffer + sock_buffer_len, &payload,
sizeof(payload));
580 sock_buffer_len +=
sizeof(payload);
581 memcpy(sock_buffer + sock_buffer_len, capture_info->payload, capture_info->len);
582 sock_buffer_len += capture_info->len;
584 ast_assert(sock_buffer_len == packet_len);
586 res =
ast_sendto(hepv3_data->sockfd, sock_buffer, sock_buffer_len, 0, &hepv3_data->remote_addr);
588 ast_log(AST_LOG_ERROR,
"Error [%d] while sending packet to HEPv3 server: %s\n",
589 errno, strerror(errno));
590 }
else if (res != sock_buffer_len) {
591 ast_log(AST_LOG_WARNING,
"Failed to send complete packet to HEPv3 server: %d of %u sent\n",
592 res, sock_buffer_len);
596 ast_free(sock_buffer);
605 if (!config || !config->general->enabled) {
627 if (!config->
general->enabled) {
632 if (ast_strlen_zero(config->
general->capture_address)) {
633 ast_log(AST_LOG_ERROR,
"Missing required configuration option 'capture_address'\n");
717 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"HEPv3 API",
718 .support_level = AST_MODULE_SUPPORT_EXTENDED,
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
static int load_module(void)
Load the module.
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Asterisk main include file. File version handling, generic pbx functions.
Run-time data derived from hepv3_global_config.
const ast_string_field capture_name
int hepv3_send_packet(struct hepv3_capture_info *capture_info)
Send a generic packet capture to HEPv3.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
const ast_string_field capture_password
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
Structure for variables, used for configurations and for channel variables.
return a reference to a taskprocessor, create one if it does not exist
Routines for integration with Homer using HEPv3.
static int hepv3_config_pre_apply(void)
Pre-apply callback for the config framework.
enum hep_uuid_type hepv3_get_uuid_type(void)
Get the preferred UUID type.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
static int reload_module(void)
Reload the module.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
static int unload_module(void)
Unload the module.
The representation of a single configuration file to be processed.
Socket address structure.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
struct hepv3_capture_info * hepv3_create_capture_info(const void *payload, size_t len)
Create a hepv3_capture_info object.
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
static void * hepv3_config_alloc(void)
HEPv3 configuration object allocation.
struct hepv3_global_config * general
static AO2_GLOBAL_OBJ_STATIC(global_config)
The module configuration container.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
Type for default option handler for unsigned integers.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_STRING_FIELD(name)
Declare a string field.
enum hep_uuid_type uuid_type
int ast_sockaddr_resolve_first_af(struct ast_sockaddr *addr, const char *name, int flag, int family)
Return the first entry from ast_sockaddr_resolve filtered by address family.
#define ast_malloc(len)
A wrapper for malloc()
The configuration settings for this module.
static int uuid_type_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Handler for the uuid_type attribute.
static struct hepv3_runtime_data * hepv3_data_alloc(struct hepv3_global_config *config)
Allocate the HEPv3 run-time data.
struct ast_sockaddr remote_addr
Their was an error and no changes were applied.
Configuration option-handling.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Type for default option handler for bools (ast_true/ast_false)
static void capture_info_dtor(void *obj)
Destructor for a hepv3_capture_info object.
static void module_config_dtor(void *obj)
Configuration object destructor.
int hepv3_is_loaded(void)
Return whether or not we're currently loaded and active.
static void * module_config_alloc(void)
Module config constructor.
Global configuration for the module.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Module has failed to load, may be in an inconsistent state.
static struct aco_type global_option
An aco_type structure to link the "general" category to the skel_global_config type.
An API for managing task processing threads that can be shared across modules.
static void hepv3_data_dtor(void *obj)
HEPv3 run-time data destructor.
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
A ast_taskprocessor structure is a singleton by name.
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
Type information about a category-level configurable object.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
CONFIG_INFO_STANDARD(cfg_info, global_config, module_config_alloc,.files=ACO_FILES(&hepv3_conf),.pre_apply_config=hepv3_config_pre_apply,.post_apply_config=hepv3_config_post_apply,)
Register information about the configs being processed by this module.
Type for default option handler for stringfields.
static void hepv3_config_post_apply(void)
Post-apply callback for the config framework.
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_cdr_config * general
Asterisk module definitions.
static int hep_queue_cb(void *data)
Callback function for the hep_queue_tp taskprocessor.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
const ast_string_field capture_address