static int request_meta_data (const char *host, const char *name) /* {{{ */ { Ganglia_metadata_msg msg; char buffer[BUFF_SIZE]; unsigned int buffer_size; XDR xdr; size_t i; memset (&msg, 0, sizeof (msg)); msg.id = gmetadata_request; msg.Ganglia_metadata_msg_u.grequest.metric_id.host = strdup (host); msg.Ganglia_metadata_msg_u.grequest.metric_id.name = strdup (name); if ((msg.Ganglia_metadata_msg_u.grequest.metric_id.host == NULL) || (msg.Ganglia_metadata_msg_u.grequest.metric_id.name == NULL)) { sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host); sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.name); return (-1); } memset (buffer, 0, sizeof (buffer)); xdrmem_create (&xdr, buffer, sizeof (buffer), XDR_ENCODE); if (!xdr_Ganglia_metadata_msg (&xdr, &msg)) { sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host); sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.name); return (-1); } buffer_size = xdr_getpos (&xdr); DEBUG ("gmond plugin: Requesting meta data for %s/%s.", host, name); pthread_mutex_lock (&mc_send_sockets_lock); for (i = 0; i < mc_send_sockets_num; i++) { ssize_t status = sendto (mc_send_sockets[i].fd, buffer, (size_t) buffer_size, /* flags = */ 0, (struct sockaddr *) &mc_send_sockets[i].addr, mc_send_sockets[i].addrlen); if (status == -1) { char errbuf[1024]; ERROR ("gmond plugin: sendto(2) failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); continue; } } pthread_mutex_unlock (&mc_send_sockets_lock); sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host); sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.name); return (0); } /* }}} int request_meta_data */
static int mc_handle_metric (void *buffer, size_t buffer_size) /* {{{ */ { XDR xdr; Ganglia_msg_formats format; xdrmem_create (&xdr, buffer, buffer_size, XDR_DECODE); xdr_Ganglia_msg_formats (&xdr, &format); xdr_setpos (&xdr, 0); switch (format) { case gmetric_ushort: case gmetric_short: case gmetric_int: case gmetric_uint: case gmetric_string: case gmetric_float: case gmetric_double: { Ganglia_value_msg msg; memset (&msg, 0, sizeof (msg)); if (xdr_Ganglia_value_msg (&xdr, &msg)) mc_handle_value_msg (&msg); break; } case gmetadata_full: case gmetadata_request: { Ganglia_metadata_msg msg; memset (&msg, 0, sizeof (msg)); if (xdr_Ganglia_metadata_msg (&xdr, &msg)) mc_handle_metadata_msg (&msg); break; } default: DEBUG ("gmond plugin: Unknown format: %i", format); return (-1); } /* switch (format) */ return (0); } /* }}} int mc_handle_metric */
int Ganglia_metadata_send_real( Ganglia_metric gmetric, Ganglia_udp_send_channels send_channels, char *override_string ) { int len, i; XDR x; char gmetricmsg[GANGLIA_MAX_MESSAGE_LEN]; Ganglia_metadata_msg msg; const apr_array_header_t *arr; const apr_table_entry_t *elts; const char *spoof = SPOOF; apr_pool_t *gm_pool=(apr_pool_t*)gmetric->pool; if (myhost[0] == '\0') apr_gethostname( (char*)myhost, APRMAXHOSTLEN+1, gm_pool); msg.id = gmetadata_full; memcpy( &(msg.Ganglia_metadata_msg_u.gfull.metric), gmetric->msg, sizeof(Ganglia_metadata_message)); msg.Ganglia_metadata_msg_u.gfull.metric_id.name = apr_pstrdup (gm_pool, gmetric->msg->name); debug_msg(" msg.Ganglia_metadata_msg_u.gfull.metric_id.name: %s\n", msg.Ganglia_metadata_msg_u.gfull.metric_id.name); if ( override_string != NULL ) { msg.Ganglia_metadata_msg_u.gfull.metric_id.host = apr_pstrdup (gm_pool, (char*)override_string); debug_msg(" msg.Ganglia_metadata_msg_u.gfull.metric_id.host: %s\n", msg.Ganglia_metadata_msg_u.gfull.metric_id.host); msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = TRUE; } else { msg.Ganglia_metadata_msg_u.gfull.metric_id.host = apr_pstrdup (gm_pool, (char*)myhost); debug_msg(" msg.Ganglia_metadata_msg_u.gfull.metric_id.host: %s\n", msg.Ganglia_metadata_msg_u.gfull.metric_id.host); msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = FALSE; } arr = apr_table_elts(gmetric->extra); elts = (const apr_table_entry_t *)arr->elts; msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_len = arr->nelts; msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_val = (Ganglia_extra_data*)apr_pcalloc(gm_pool, sizeof(Ganglia_extra_data)*arr->nelts); /* add all of the metadata to the packet */ for (i = 0; i < arr->nelts; ++i) { if (elts[i].key == NULL) continue; /* Replace the host name with the spoof host if it exists in the metadata */ if ((apr_toupper(elts[i].key[0]) == spoof[0]) && strcasecmp(SPOOF_HOST, elts[i].key) == 0) { msg.Ganglia_metadata_msg_u.gfull.metric_id.host = apr_pstrdup (gm_pool, elts[i].val); msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = TRUE; } if ((apr_toupper(elts[i].key[0]) == spoof[0]) && strcasecmp(SPOOF_HEARTBEAT, elts[i].key) == 0) { msg.Ganglia_metadata_msg_u.gfull.metric_id.name = apr_pstrdup (gm_pool, "heartbeat"); msg.Ganglia_metadata_msg_u.gfull.metric.name = msg.Ganglia_metadata_msg_u.gfull.metric_id.name; msg.Ganglia_metadata_msg_u.gfull.metric_id.spoof = TRUE; } msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_val[i].name = apr_pstrdup(gm_pool, elts[i].key); msg.Ganglia_metadata_msg_u.gfull.metric.metadata.metadata_val[i].data = apr_pstrdup(gm_pool, elts[i].val); } /* Send the message */ xdrmem_create(&x, gmetricmsg, GANGLIA_MAX_MESSAGE_LEN, XDR_ENCODE); if(!xdr_Ganglia_metadata_msg(&x, &msg)) { return 1; } len = xdr_getpos(&x); /* Send the encoded data along...*/ return Ganglia_udp_send_message( send_channels, gmetricmsg, len); }
static int create_sockets(socket_entry_t **ret_sockets, /* {{{ */ size_t *ret_sockets_num, const char *node, const char *service, int listen) { struct addrinfo *ai_list; int ai_return; socket_entry_t *sockets = NULL; size_t sockets_num = 0; int status; if (*ret_sockets != NULL) return (EINVAL); struct addrinfo ai_hints = {.ai_family = AF_UNSPEC, .ai_flags = AI_ADDRCONFIG | AI_PASSIVE, .ai_protocol = IPPROTO_UDP, .ai_socktype = SOCK_DGRAM}; ai_return = getaddrinfo(node, service, &ai_hints, &ai_list); if (ai_return != 0) { char errbuf[1024]; ERROR("gmond plugin: getaddrinfo (%s, %s) failed: %s", (node == NULL) ? "(null)" : node, (service == NULL) ? "(null)" : service, (ai_return == EAI_SYSTEM) ? sstrerror(errno, errbuf, sizeof(errbuf)) : gai_strerror(ai_return)); return (-1); } for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) /* {{{ */ { socket_entry_t *tmp; tmp = realloc(sockets, (sockets_num + 1) * sizeof(*sockets)); if (tmp == NULL) { ERROR("gmond plugin: realloc failed."); continue; } sockets = tmp; sockets[sockets_num].fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (sockets[sockets_num].fd < 0) { char errbuf[1024]; ERROR("gmond plugin: socket failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); continue; } assert(sizeof(sockets[sockets_num].addr) >= ai_ptr->ai_addrlen); memcpy(&sockets[sockets_num].addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen); sockets[sockets_num].addrlen = ai_ptr->ai_addrlen; /* Sending socket: Open only one socket and don't bind it. */ if (listen == 0) { sockets_num++; break; } else { int yes = 1; status = setsockopt(sockets[sockets_num].fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); if (status != 0) { char errbuf[1024]; WARNING("gmond plugin: setsockopt(2) failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); } } status = bind(sockets[sockets_num].fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); if (status != 0) { char errbuf[1024]; ERROR("gmond plugin: bind failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); close(sockets[sockets_num].fd); continue; } if (ai_ptr->ai_family == AF_INET) { struct sockaddr_in *addr; int loop; addr = (struct sockaddr_in *)ai_ptr->ai_addr; if (!IN_MULTICAST(ntohl(addr->sin_addr.s_addr))) { sockets_num++; continue; } loop = 1; status = setsockopt(sockets[sockets_num].fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&loop, sizeof(loop)); if (status != 0) { char errbuf[1024]; WARNING("gmond plugin: setsockopt(2) failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); } struct ip_mreq mreq = {.imr_multiaddr.s_addr = addr->sin_addr.s_addr, .imr_interface.s_addr = htonl(INADDR_ANY)}; status = setsockopt(sockets[sockets_num].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)); if (status != 0) { char errbuf[1024]; WARNING("gmond plugin: setsockopt(2) failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); } } /* if (ai_ptr->ai_family == AF_INET) */ else if (ai_ptr->ai_family == AF_INET6) { struct sockaddr_in6 *addr; int loop; addr = (struct sockaddr_in6 *)ai_ptr->ai_addr; if (!IN6_IS_ADDR_MULTICAST(&addr->sin6_addr)) { sockets_num++; continue; } loop = 1; status = setsockopt(sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (void *)&loop, sizeof(loop)); if (status != 0) { char errbuf[1024]; WARNING("gmond plugin: setsockopt(2) failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); } struct ipv6_mreq mreq = { .ipv6mr_interface = 0 /* any */ }; memcpy(&mreq.ipv6mr_multiaddr, &addr->sin6_addr, sizeof(addr->sin6_addr)); status = setsockopt(sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)); if (status != 0) { char errbuf[1024]; WARNING("gmond plugin: setsockopt(2) failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); } } /* if (ai_ptr->ai_family == AF_INET6) */ sockets_num++; } /* }}} for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) */ freeaddrinfo(ai_list); if (sockets_num == 0) { sfree(sockets); return (-1); } *ret_sockets = sockets; *ret_sockets_num = sockets_num; return (0); } /* }}} int create_sockets */ static int request_meta_data(const char *host, const char *name) /* {{{ */ { Ganglia_metadata_msg msg = {0}; char buffer[BUFF_SIZE] = {0}; unsigned int buffer_size; XDR xdr; msg.id = gmetadata_request; msg.Ganglia_metadata_msg_u.grequest.metric_id.host = strdup(host); msg.Ganglia_metadata_msg_u.grequest.metric_id.name = strdup(name); if ((msg.Ganglia_metadata_msg_u.grequest.metric_id.host == NULL) || (msg.Ganglia_metadata_msg_u.grequest.metric_id.name == NULL)) { sfree(msg.Ganglia_metadata_msg_u.grequest.metric_id.host); sfree(msg.Ganglia_metadata_msg_u.grequest.metric_id.name); return (-1); } xdrmem_create(&xdr, buffer, sizeof(buffer), XDR_ENCODE); if (!xdr_Ganglia_metadata_msg(&xdr, &msg)) { sfree(msg.Ganglia_metadata_msg_u.grequest.metric_id.host); sfree(msg.Ganglia_metadata_msg_u.grequest.metric_id.name); return (-1); } buffer_size = xdr_getpos(&xdr); DEBUG("gmond plugin: Requesting meta data for %s/%s.", host, name); pthread_mutex_lock(&mc_send_sockets_lock); for (size_t i = 0; i < mc_send_sockets_num; i++) { ssize_t status = sendto(mc_send_sockets[i].fd, buffer, (size_t)buffer_size, /* flags = */ 0, (struct sockaddr *)&mc_send_sockets[i].addr, mc_send_sockets[i].addrlen); if (status == -1) { char errbuf[1024]; ERROR("gmond plugin: sendto(2) failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); continue; } } pthread_mutex_unlock(&mc_send_sockets_lock); sfree(msg.Ganglia_metadata_msg_u.grequest.metric_id.host); sfree(msg.Ganglia_metadata_msg_u.grequest.metric_id.name); return (0); } /* }}} int request_meta_data */