]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
network plugin: Add a new metadata "network:ip_address" 3191/head
authorTakuro Ashie <ashie@clear-code.com>
Wed, 26 Feb 2020 09:33:40 +0000 (18:33 +0900)
committerTakuro Ashie <ashie@clear-code.com>
Wed, 26 Feb 2020 09:33:40 +0000 (18:33 +0900)
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 <ashie@clear-code.com>
src/network.c
src/network_test.c

index 613caa73548864ee0d9a8d049153a39be0b10740..74d357af1a0f881fba5963bafadeaee0b3424326 100644 (file)
@@ -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;
index ae4875cc2bb1b4426ad4226ec0ea87d381ada60d..201412f71f057999c42bb6f1652e25a18313d350 100644 (file)
@@ -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);