From: Florian octo Forster Date: Wed, 27 Feb 2008 09:22:19 +0000 (+0100) Subject: network plugin: Align write access to the send buffer. X-Git-Tag: collectd-4.2.5~8 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=4f3a014ba130cfd6f61b3f16aa74d527e1ab7000;p=collectd.git network plugin: Align write access to the send buffer. SPARC and possibly other architectures cannot access arbitrary memory locations. This caused a `bus error' on SPARC when the network plugin was loaded. This change hopefully fixes this problem. --- diff --git a/src/network.c b/src/network.c index 17038a45..469baf7b 100644 --- a/src/network.c +++ b/src/network.c @@ -306,37 +306,83 @@ static int cache_check (const char *type, const value_list_t *vl) static int write_part_values (char **ret_buffer, int *ret_buffer_len, const data_set_t *ds, const value_list_t *vl) { - part_values_t pv; + char *packet_ptr; + int packet_len; + int num_values; + + part_header_t pkg_ph; + uint16_t pkg_num_values; + uint8_t *pkg_values_types; + value_t *pkg_values; + + int offset; int i; - i = 6 + (9 * vl->values_len); - if (*ret_buffer_len < i) + num_values = vl->values_len; + packet_len = sizeof (part_header_t) + sizeof (uint16_t) + + (num_values * sizeof (uint8_t)) + + (num_values * sizeof (value_t)); + + if (*ret_buffer_len < packet_len) return (-1); - *ret_buffer_len -= i; - pv.head = (part_header_t *) *ret_buffer; - pv.num_values = (uint16_t *) (pv.head + 1); - pv.values_types = (uint8_t *) (pv.num_values + 1); - pv.values = (value_t *) (pv.values_types + vl->values_len); - *ret_buffer = (void *) (pv.values + vl->values_len); + pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t)); + if (pkg_values_types == NULL) + { + ERROR ("network plugin: write_part_values: malloc failed."); + return (-1); + } - pv.head->type = htons (TYPE_VALUES); - pv.head->length = htons (6 + (9 * vl->values_len)); - *pv.num_values = htons ((uint16_t) vl->values_len); - - for (i = 0; i < vl->values_len; i++) + pkg_values = (value_t *) malloc (num_values * sizeof (value_t)); + if (pkg_values == NULL) + { + free (pkg_values_types); + ERROR ("network plugin: write_part_values: malloc failed."); + return (-1); + } + + pkg_ph.type = htons (TYPE_VALUES); + pkg_ph.length = htons (packet_len); + + pkg_num_values = htons ((uint16_t) vl->values_len); + + for (i = 0; i < num_values; i++) { if (ds->ds[i].type == DS_TYPE_COUNTER) { - pv.values_types[i] = DS_TYPE_COUNTER; - pv.values[i].counter = htonll (vl->values[i].counter); + pkg_values_types[i] = DS_TYPE_COUNTER; + pkg_values[i].counter = htonll (vl->values[i].counter); } else { - pv.values_types[i] = DS_TYPE_GAUGE; - pv.values[i].gauge = vl->values[i].gauge; + pkg_values_types[i] = DS_TYPE_GAUGE; + pkg_values[i].gauge = vl->values[i].gauge; } - } /* for (values) */ + } + + /* + * Use `memcpy' to write everything to the buffer, because the pointer + * may be unaligned and some architectures, such as SPARC, can't handle + * that. + */ + packet_ptr = *ret_buffer; + offset = 0; + memcpy (packet_ptr + offset, &pkg_ph, sizeof (pkg_ph)); + offset += sizeof (pkg_ph); + memcpy (packet_ptr + offset, &pkg_num_values, sizeof (pkg_num_values)); + offset += sizeof (pkg_num_values); + memcpy (packet_ptr + offset, pkg_values_types, num_values * sizeof (uint8_t)); + offset += num_values * sizeof (uint8_t); + memcpy (packet_ptr + offset, pkg_values, num_values * sizeof (value_t)); + offset += num_values * sizeof (value_t); + + assert (offset == packet_len); + + *ret_buffer = packet_ptr + packet_len; + *ret_buffer_len -= packet_len; + + free (pkg_values_types); + free (pkg_values); return (0); } /* int write_part_values */ @@ -344,20 +390,34 @@ static int write_part_values (char **ret_buffer, int *ret_buffer_len, static int write_part_number (char **ret_buffer, int *ret_buffer_len, int type, uint64_t value) { - part_number_t pn; + char *packet_ptr; + int packet_len; + + part_header_t pkg_head; + uint64_t pkg_value; + + int offset; + + packet_len = sizeof (pkg_head) + sizeof (pkg_value); - if (*ret_buffer_len < 12) + if (*ret_buffer_len < packet_len) return (-1); - pn.head = (part_header_t *) *ret_buffer; - pn.value = (uint64_t *) (pn.head + 1); + pkg_head.type = htons (type); + pkg_head.length = htons (packet_len); + pkg_value = htonll (value); - pn.head->type = htons (type); - pn.head->length = htons (12); - *pn.value = htonll (value); + packet_ptr = *ret_buffer; + offset = 0; + memcpy (packet_ptr + offset, &pkg_head, sizeof (pkg_head)); + offset += sizeof (pkg_head); + memcpy (packet_ptr + offset, &pkg_value, sizeof (pkg_value)); + offset += sizeof (pkg_value); - *ret_buffer = (char *) (pn.value + 1); - *ret_buffer_len -= 12; + assert (offset == packet_len); + + *ret_buffer = packet_ptr + packet_len; + *ret_buffer_len -= packet_len; return (0); } /* int write_part_number */ @@ -365,23 +425,33 @@ static int write_part_number (char **ret_buffer, int *ret_buffer_len, static int write_part_string (char **ret_buffer, int *ret_buffer_len, int type, const char *str, int str_len) { - part_string_t ps; - int len; + char *packet_ptr; + int packet_len; + + part_header_t pkg_head; + + int offset; - len = 4 + str_len + 1; - if (*ret_buffer_len < len) + packet_len = sizeof (pkg_head) + str_len + 1; + if (*ret_buffer_len < packet_len) return (-1); - *ret_buffer_len -= len; - ps.head = (part_header_t *) *ret_buffer; - ps.value = (char *) (ps.head + 1); + pkg_head.type = htons (type); + pkg_head.length = htons (packet_len); + + packet_ptr = *ret_buffer; + offset = 0; + memcpy (packet_ptr + offset, &pkg_head, sizeof (pkg_head)); + offset += sizeof (pkg_head); + memcpy (packet_ptr + offset, str, str_len); + offset += str_len; + memset (packet_ptr + offset, '\0', 1); + offset += 1; + + assert (offset == packet_len); - ps.head->type = htons ((uint16_t) type); - ps.head->length = htons ((uint16_t) str_len + 5); - if (str_len > 0) - memcpy (ps.value, str, str_len); - ps.value[str_len] = '\0'; - *ret_buffer = (void *) (ps.value + (str_len + 1)); + *ret_buffer = packet_ptr + packet_len; + *ret_buffer_len -= packet_len; return (0); } /* int write_part_string */