From: Takuro Ashie Date: Wed, 26 Feb 2020 09:33:40 +0000 (+0900) Subject: network plugin: Add a new metadata "network:ip_address" X-Git-Tag: collectd-5.11.0~32^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=acf55f09f95be2afeef2fb10241d4db2054296b0;p=thirdparty%2Fcollectd.git network plugin: Add a new metadata "network:ip_address" Although the telemetry data already have the "host" identifier, it can be determined by clients. This additional metadata will help you to detect spoofing at server side. It will also help you to filter the data by sender's address. Signed-off-by: Takuro Ashie --- diff --git a/src/network.c b/src/network.c index 613caa735..74d357af1 100644 --- a/src/network.c +++ b/src/network.c @@ -256,6 +256,7 @@ struct receive_list_entry_s { char *data; int data_len; int fd; + struct sockaddr_storage sender; struct receive_list_entry_s *next; }; typedef struct receive_list_entry_s receive_list_entry_t; @@ -393,7 +394,8 @@ static bool check_send_notify_okay(const notification_t *n) /* {{{ */ } /* }}} bool check_send_notify_okay */ static int network_dispatch_values(value_list_t *vl, /* {{{ */ - const char *username) { + const char *username, + struct sockaddr_storage *address) { int status; if ((vl->time == 0) || (strlen(vl->host) == 0) || (strlen(vl->plugin) == 0) || @@ -439,6 +441,27 @@ static int network_dispatch_values(value_list_t *vl, /* {{{ */ } } + if (address != NULL) { + char host[48]; + status = getnameinfo((struct sockaddr *)address, + sizeof(struct sockaddr_storage), host, sizeof(host), + NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + if (status != 0) { + ERROR("network plugin: getnameinfo failed: %s", gai_strerror(status)); + meta_data_destroy(vl->meta); + vl->meta = NULL; + return status; + } + + status = meta_data_add_string(vl->meta, "network:ip_address", host); + if (status != 0) { + ERROR("network plugin: meta_data_add_string failed."); + meta_data_destroy(vl->meta); + vl->meta = NULL; + return status; + } + } + plugin_dispatch_values(vl); stats_values_dispatched++; @@ -972,7 +995,8 @@ static int parse_part_string(void **ret_buffer, size_t *ret_buffer_len, #define PP_SIGNED 0x01 #define PP_ENCRYPTED 0x02 static int parse_packet(sockent_t *se, void *buffer, size_t buffer_size, - int flags, const char *username); + int flags, const char *username, + struct sockaddr_storage *sender); #define BUFFER_READ(p, s) \ do { \ @@ -983,7 +1007,7 @@ static int parse_packet(sockent_t *se, void *buffer, size_t buffer_size, #if HAVE_GCRYPT_H static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_len, - int flags) { + int flags, struct sockaddr_storage *sender) { static c_complain_t complain_no_users = C_COMPLAIN_INIT_STATIC; char *buffer; @@ -1098,7 +1122,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ pss.username); } else { parse_packet(se, buffer + buffer_offset, buffer_len - buffer_offset, - flags | PP_SIGNED, pss.username); + flags | PP_SIGNED, pss.username, sender); } sfree(secret); @@ -1114,7 +1138,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ #else /* if !HAVE_GCRYPT_H */ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_size, - int flags) { + int flags, struct sockaddr_storage *sender) { static int warning_has_been_printed; char *buffer; @@ -1146,7 +1170,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ } parse_packet(se, buffer + part_len, buffer_size - part_len, flags, - /* username = */ NULL); + /* username = */ NULL, sender); *ret_buffer = buffer + buffer_size; *ret_buffer_size = 0; @@ -1158,7 +1182,7 @@ static int parse_part_sign_sha256(sockent_t *se, /* {{{ */ #if HAVE_GCRYPT_H static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_len, - int flags) { + int flags, struct sockaddr_storage *sender) { char *buffer = *ret_buffer; size_t buffer_len = *ret_buffer_len; size_t payload_len; @@ -1254,7 +1278,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ } parse_packet(se, buffer + buffer_offset, payload_len, flags | PP_ENCRYPTED, - pea.username); + pea.username, sender); /* Update return values */ *ret_buffer = buffer + part_size; @@ -1269,7 +1293,7 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ #else /* if !HAVE_GCRYPT_H */ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ void **ret_buffer, size_t *ret_buffer_size, - int flags) { + int flags, struct sockaddr_storage *sender) { static int warning_has_been_printed; char *buffer; @@ -1314,7 +1338,8 @@ static int parse_part_encr_aes256(sockent_t *se, /* {{{ */ static int parse_packet(sockent_t *se, /* {{{ */ void *buffer, size_t buffer_size, int flags, - const char *username) { + const char *username, + struct sockaddr_storage *address) { int status; value_list_t vl = VALUE_LIST_INIT; @@ -1348,7 +1373,8 @@ static int parse_packet(sockent_t *se, /* {{{ */ break; if (pkg_type == TYPE_ENCR_AES256) { - status = parse_part_encr_aes256(se, &buffer, &buffer_size, flags); + status = + parse_part_encr_aes256(se, &buffer, &buffer_size, flags, address); if (status != 0) { ERROR("network plugin: Decrypting AES256 " "part failed " @@ -1371,7 +1397,8 @@ static int parse_packet(sockent_t *se, /* {{{ */ } #endif /* HAVE_GCRYPT_H */ else if (pkg_type == TYPE_SIGN_SHA256) { - status = parse_part_sign_sha256(se, &buffer, &buffer_size, flags); + status = + parse_part_sign_sha256(se, &buffer, &buffer_size, flags, address); if (status != 0) { ERROR("network plugin: Verifying HMAC-SHA-256 " "signature failed " @@ -1399,7 +1426,7 @@ static int parse_packet(sockent_t *se, /* {{{ */ if (status != 0) break; - network_dispatch_values(&vl, username); + network_dispatch_values(&vl, username, address); sfree(vl.values); } else if (pkg_type == TYPE_TIME) { @@ -2222,7 +2249,7 @@ static void *dispatch_thread(void __attribute__((unused)) * arg) /* {{{ */ } parse_packet(se, ent->data, ent->data_len, /* flags = */ 0, - /* username = */ NULL); + /* username = */ NULL, &ent->sender); sfree(ent->data); sfree(ent); } /* while (42) */ @@ -2263,8 +2290,12 @@ static int network_receive(void) /* {{{ */ continue; status--; - buffer_len = recv(listen_sockets_pollfd[i].fd, buffer, sizeof(buffer), - 0 /* no flags */); + struct sockaddr_storage address; + socklen_t length = sizeof(address); + memset(&address, 0, length); + buffer_len = + recvfrom(listen_sockets_pollfd[i].fd, buffer, sizeof(buffer), + 0 /* no flags */, (struct sockaddr *)&address, &length); if (buffer_len < 0) { status = (errno != 0) ? errno : -1; ERROR("network plugin: recv(2) failed: %s", STRERRNO); @@ -2297,6 +2328,7 @@ static int network_receive(void) /* {{{ */ memcpy(ent->data, buffer, buffer_len); ent->data_len = buffer_len; + memcpy(&ent->sender, &address, sizeof(ent->sender)); if (private_list_head == NULL) private_list_head = ent; diff --git a/src/network_test.c b/src/network_test.c index ae4875cc2..201412f71 100644 --- a/src/network_test.c +++ b/src/network_test.c @@ -241,7 +241,7 @@ DEF_TEST(parse_packet) { size_t buffer_size = sizeof(buffer); EXPECT_EQ_INT(0, decode_string(raw_packet_data[i], buffer, &buffer_size)); - EXPECT_EQ_INT(0, parse_packet(&se, buffer, buffer_size, 0, NULL)); + EXPECT_EQ_INT(0, parse_packet(&se, buffer, buffer_size, 0, NULL, NULL)); } EXPECT_EQ_INT(139, (int)stats_values_dispatched);