write_tsdb: enable TCP keepalive on network socket
[collectd.git] / src / uuid.c
index e0de0d9..8976626 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/uuid.c
  * Copyright (C) 2007  Red Hat Inc.
+ * Copyright (C) 2015  Ruben Kerkhof
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "configfile.h"
 #include "plugin.h"
 
-#if HAVE_LIBHAL
+#if HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+#if HAVE_LIBHAL_H
 #include <libhal.h>
 #endif
 
 #define UUID_PRINTABLE_COMPACT_LENGTH  (UUID_RAW_LENGTH * 2)
 #define UUID_PRINTABLE_NORMAL_LENGTH  (UUID_PRINTABLE_COMPACT_LENGTH + 4)
 
-#define HANDLE_PREFIX "Handle"
-#define SYSINFO_PREFIX "System Information"
-#define ALT_SYSINFO_PREFIX "\tSystem Information"
-#define UUID_PREFIX "\tUUID:"
-#define ALT_UUID_PREFIX "\t\tUUID:"
+static char *uuidfile = NULL;
+
+static const char *config_keys[] = {
+    "UUIDFile"
+};
 
 static int
 looks_like_a_uuid (const char *uuid)
 {
     int len;
 
-    if (!uuid) return 0;
+    if (!uuid)
+        return (0);
 
     len = strlen (uuid);
 
     if (len < UUID_PRINTABLE_COMPACT_LENGTH)
-        return 0;
+        return (0);
 
     while (*uuid) {
-        if (!isxdigit (*uuid) && *uuid != '-') return 0;
+        if (!isxdigit ((int)*uuid) && *uuid != '-')
+            return (0);
         uuid++;
     }
-    return 1;
+    return (1);
 }
 
 static char *
 uuid_parse_dmidecode(FILE *file)
 {
     char line[1024];
-    int inSysInfo = 0;
-
-    for (;;) {
-        if (!fgets(line, sizeof(line)/sizeof(char), file)) {
-            return NULL;
-        }
-        if (strncmp(line, HANDLE_PREFIX,
-                    (sizeof(HANDLE_PREFIX)/sizeof(char))-1) == 0) {
-            /*printf("Got handle %s\n", line);*/
-            inSysInfo = 0;
-        } else if (strncmp(line, SYSINFO_PREFIX,
-                           (sizeof(SYSINFO_PREFIX)/sizeof(char))-1) == 0) {
-            /*printf("Got system info %s\n", line);*/
-            inSysInfo = 1;
-        } else if (strncmp(line, ALT_SYSINFO_PREFIX,
-                           (sizeof(ALT_SYSINFO_PREFIX)/sizeof(char))-1) == 0) {
-            /*printf("Got alt system info %s\n", line);*/
-            inSysInfo = 1;
-        }
-        
-        if (inSysInfo) {
-            if (strncmp(line, UUID_PREFIX,
-                        (sizeof(UUID_PREFIX)/sizeof(char))-1) == 0) {
-                char *uuid = line + (sizeof(UUID_PREFIX)/sizeof(char));
-                /*printf("Got uuid [%s]\n", uuid);*/
-                if (looks_like_a_uuid (uuid))
-                    return strdup (uuid);
-            }
-            if (strncmp(line, ALT_UUID_PREFIX,
-                        (sizeof(ALT_UUID_PREFIX)/sizeof(char))-1) == 0) {
-                char *uuid = line + (sizeof(ALT_UUID_PREFIX)/sizeof(char));
-                /*printf("Got alt uuid [%s]\n", uuid);*/
-                if (looks_like_a_uuid (uuid))
-                    return strdup (uuid);
-            }
-        }
+
+    while (fgets (line, sizeof (line), file) != NULL)
+    {
+        char *fields[4];
+        int fields_num;
+
+        strstripnewline (line);
+
+        /* Look for a line reading:
+         *   UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+         */
+        fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields));
+        if (fields_num != 2)
+            continue;
+
+        if (strcmp("UUID:", fields[0]) != 0)
+            continue;
+
+        if (!looks_like_a_uuid (fields[1]))
+            continue;
+
+        return (strdup (fields[1]));
     }
-    return NULL;
+    return (NULL);
 }
 
 static char *
 uuid_get_from_dmidecode(void)
 {
-    FILE *dmidecode = popen("dmidecode 2>/dev/null", "r");
+    FILE *dmidecode = popen("dmidecode -t system 2>/dev/null", "r");
     char *uuid;
 
-    if (!dmidecode) {
-        return NULL;
-    }
-    
+    if (!dmidecode)
+        return (NULL);
+
     uuid = uuid_parse_dmidecode(dmidecode);
 
     pclose(dmidecode);
-    return uuid;
+    return (uuid);
+}
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+static char *
+uuid_get_from_sysctlbyname(const char *name)
+{
+    char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
+    size_t len = sizeof (uuid);
+    if (sysctlbyname(name, &uuid, &len, NULL, 0) == -1)
+        return NULL;
+    return (strdup (uuid));
 }
+#elif defined(__OpenBSD__)
+static char *
+uuid_get_from_sysctl(void)
+{
+    char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
+    size_t len = sizeof (uuid);
+    int mib[2];
 
-#if HAVE_LIBHAL
+    mib[0] = CTL_HW;
+    mib[1] = HW_UUID;
+
+    if (sysctl(mib, 2, uuid, &len, NULL, 0) == -1)
+        return NULL;
+    return (strdup (uuid));
+}
+#endif
+
+#if HAVE_LIBHAL_H
 
 #define UUID_PATH "/org/freedesktop/Hal/devices/computer"
 #define UUID_PROPERTY "smbios.system.uuid"
@@ -136,50 +156,42 @@ uuid_get_from_hal(void)
 
     dbus_error_init(&error);
 
-    if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) ) {
+    if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)))
         goto bailout_nobus;
-    }
 
     ctx = libhal_ctx_new();
     libhal_ctx_set_dbus_connection(ctx, con);
 
-    if (!libhal_ctx_init(ctx, &error)) {
+    if (!libhal_ctx_init(ctx, &error))
         goto bailout;
-    }
 
     if (!libhal_device_property_exists(ctx,
                                        UUID_PATH,
                                        UUID_PROPERTY,
-                                       &error)) {
+                                       &error))
         goto bailout;
-    }
 
     char *uuid  = libhal_device_get_property_string(ctx,
                                                     UUID_PATH,
                                                     UUID_PROPERTY,
                                                     &error);
-    if (looks_like_a_uuid (uuid)) {
-        return uuid;
-    }
+    if (looks_like_a_uuid (uuid))
+        return (uuid);
 
  bailout:
     {
         DBusError ctxerror;
         dbus_error_init(&ctxerror);
-        if (!(libhal_ctx_shutdown(ctx, &ctxerror))) {
+        if (!(libhal_ctx_shutdown(ctx, &ctxerror)))
             dbus_error_free(&ctxerror);
-        }
     }
 
     libhal_ctx_free(ctx);
-    //dbus_connection_unref(con);
 
  bailout_nobus:
-    if (dbus_error_is_set(&error)) {
-        /*printf("Error %s\n", error.name);*/
+    if (dbus_error_is_set(&error))
         dbus_error_free(&error);
-    }
-    return NULL;
+    return (NULL);
 }
 #endif
 
@@ -187,68 +199,77 @@ static char *
 uuid_get_from_file(const char *path)
 {
     FILE *file;
-    char uuid[UUID_PRINTABLE_NORMAL_LENGTH+1];
+    char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1] = "";
 
-    if (!(file = fopen(path, "r"))) {
-        return NULL;
-    }
+    file = fopen (path, "r");
+    if (file == NULL)
+        return (NULL);
 
     if (!fgets(uuid, sizeof(uuid), file)) {
         fclose(file);
-        return NULL;
+        return (NULL);
     }
     fclose(file);
+    strstripnewline (uuid);
 
-    return strdup (uuid);
+    return (strdup (uuid));
 }
 
-static char *uuidfile = NULL;
-
 static char *
 uuid_get_local(void)
 {
     char *uuid;
 
     /* Check /etc/uuid / UUIDFile before any other method. */
-    if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL){
-        return uuid;
-    }
+    if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL)
+        return (uuid);
+
+#if defined(__APPLE__)
+    if ((uuid = uuid_get_from_sysctlbyname("kern.uuid")) != NULL)
+        return (uuid);
+#elif defined(__FreeBSD__)
+    if ((uuid = uuid_get_from_sysctlbyname("kern.hostuuid")) != NULL)
+        return (uuid);
+#elif defined(__NetBSD__)
+    if ((uuid = uuid_get_from_sysctlbyname("machdep.dmi.system-uuid")) != NULL)
+        return (uuid);
+#elif defined(__OpenBSD__)
+    if ((uuid = uuid_get_from_sysctl()) != NULL)
+        return (uuid);
+#elif defined(__linux__)
+    if ((uuid = uuid_get_from_file("/sys/class/dmi/id/product_uuid")) != NULL)
+        return (uuid);
+#endif
 
-#if HAVE_LIBHAL
-    if ((uuid = uuid_get_from_hal()) != NULL) {
-        return uuid;
-    }
+#if HAVE_LIBHAL_H
+    if ((uuid = uuid_get_from_hal()) != NULL)
+        return (uuid);
 #endif
 
-    if ((uuid = uuid_get_from_dmidecode()) != NULL) {
-        return uuid;
-    }
+    if ((uuid = uuid_get_from_dmidecode()) != NULL)
+        return (uuid);
 
-    if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL) {
-        return uuid;
-    }
+#if defined(__linux__)
+    if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL)
+        return (uuid);
+#endif
 
-    return NULL;
+    return (NULL);
 }
 
-static const char *config_keys[] = {
-    "UUIDFile",
-    NULL
-};
-#define NR_CONFIG_KEYS ((sizeof config_keys / sizeof config_keys[0]) - 1)
-
 static int
 uuid_config (const char *key, const char *value)
 {
     if (strcasecmp (key, "UUIDFile") == 0) {
-        if (uuidfile) {
-            ERROR ("UUIDFile given twice in configuration file");
-            return 1;
-        }
-        uuidfile = strdup (value);
-        return 0;
+        char *tmp = strdup (value);
+        if (tmp == NULL)
+            return (-1);
+        sfree (uuidfile);
+        uuidfile = tmp;
+        return (0);
     }
-    return 0;
+
+    return (1);
 }
 
 static int
@@ -259,18 +280,18 @@ uuid_init (void)
     if (uuid) {
         sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
         sfree (uuid);
-        return 0;
+        return (0);
     }
 
     WARNING ("uuid: could not read UUID using any known method");
-    return 0;
+    return (0);
 }
 
 void module_register (void)
 {
-       plugin_register_config ("uuid", uuid_config,
-                            config_keys, NR_CONFIG_KEYS);
-       plugin_register_init ("uuid", uuid_init);
+    plugin_register_config ("uuid", uuid_config,
+            config_keys, STATIC_ARRAY_SIZE (config_keys));
+    plugin_register_init ("uuid", uuid_init);
 }
 
 /*