ntpd branch: The ntpd plugin now resolves the `127.127.$id.*' addresses to the refere...
[collectd.git] / src / ntpd.c
index 95af8ba..f4b911d 100644 (file)
@@ -45,6 +45,9 @@
 #if HAVE_NETINET_IN_H
 # include <netinet/in.h>
 #endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h> /* inet_ntoa */
+#endif
 #if HAVE_NETINET_TCP_H
 # include <netinet/tcp.h>
 #endif
 # include <sys/poll.h>
 #endif
 
+static char *config_keys[] =
+{
+       "Host",
+       "Port",
+       NULL
+};
+static int config_keys_num = 2;
+
 /* drift */
 static char *time_offset_file = "ntpd/time_offset-%s.rrd";
 static char *time_offset_ds_def[] =
@@ -87,6 +98,9 @@ static char *ntpd_port = NULL;
 #define IMPL_XNTPD 3
 #define FP_FRAC 65536.0
 
+#define REFCLOCK_ADDR 0x7f7f0000 /* 127.127.0.0 */
+#define REFCLOCK_MASK 0xffff0000 /* 255.255.0.0 */
+
 /* This structure is missing the message authentication code, since collectd
  * doesn't use it. */
 struct req_pkt
@@ -246,10 +260,52 @@ struct info_kernel
        int32_t  errcnt;
        int32_t  stbcnt;
 };
+
+/* List of reference clock names */
+static char *refclock_names[] =
+{
+       "UNKNOWN",    "LOCAL",        "GPS_TRAK",   "WWV_PST",     /*  0- 3 */
+       "SPECTRACOM", "TRUETIME",     "IRIG_AUDIO", "CHU_AUDIO",   /*  4- 7 */
+       "GENERIC",    "GPS_MX4200",   "GPS_AS2201", "GPS_ARBITER", /*  8-11 */
+       "IRIG_TPRO",  "ATOM_LEITCH",  "MSF_EES",    "GPSTM_TRUE",  /* 12-15 */
+       "GPS_BANC",   "GPS_DATUM",    "ACTS_NIST",  "WWV_HEATH",   /* 16-19 */
+       "GPS_NMEA",   "GPS_VME",      "PPS",        "ACTS_PTB",    /* 20-23 */
+       "ACTS_USNO",  "TRUETIME",     "GPS_HP",     "MSF_ARCRON",  /* 24-27 */
+       "SHM",        "GPS_PALISADE", "GPS_ONCORE", "GPS_JUPITER", /* 28-31 */
+       "CHRONOLOG",  "DUMBCLOCK",    "ULINK_M320", "PCF",         /* 32-35 */
+       "WWV_AUDIO",  "GPS_FG",       "HOPF_S",     "HOPF_P",      /* 36-39 */
+       "JJY",        "TT_IRIG",      "GPS_ZYFER",  "GPS_RIPENCC", /* 40-43 */
+       "NEOCLK4X",   NULL                                         /* 44    */
+};
+static int refclock_names_num = 45;
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * End of the copied stuff..                                         *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
+static int ntpd_config (char *key, char *value)
+{
+       if (strcasecmp (key, "host") == 0)
+       {
+               if (ntpd_host != NULL)
+                       free (ntpd_host);
+               if ((ntpd_host = strdup (value)) == NULL)
+                       return (1);
+       }
+       else if (strcasecmp (key, "port") == 0)
+       {
+               if (ntpd_port != NULL)
+                       free (ntpd_port);
+               if ((ntpd_port = strdup (value)) == NULL)
+                       return (1);
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+}
+
 static void ntpd_init (void)
 {
        return;
@@ -797,15 +853,79 @@ static void ntpd_read (void)
        {
                struct info_peer_summary *ptr;
                double offset;
+
+               char peername[512];
+               
                ptr = ps + i;
 
-               if (((ntohl (ptr->dstadr) & 0x7F000000) == 0x7F000000) || (ptr->dstadr == 0))
+               /*
+               if (((ntohl (ptr->dstadr) & 0xFFFFFF00) == 0x7F000000) || (ptr->dstadr == 0))
                        continue;
+                       */
 
                /* Convert the `long floating point' offset value to double */
                M_LFPTOD (ntohl (ptr->offset_int), ntohl (ptr->offset_frc), offset);
 
+               if (ptr->v6_flag)
+               {
+                       status = getnameinfo ((const struct sockaddr *) &ptr->srcadr6,
+                                       sizeof (ptr->srcadr6),
+                                       peername, sizeof (peername),
+                                       NULL, 0, 0 /* no flags */);
+                       if (status != 0)
+                       {
+                               syslog (LOG_ERR, "ntpd plugin: getnameinfo failed: %s",
+                                               status == EAI_SYSTEM
+                                               ? strerror (errno)
+                                               : gai_strerror (status));
+                               continue;
+                       }
+               }
+               else if ((ntohl (ptr->srcadr) & REFCLOCK_MASK) == REFCLOCK_ADDR)
+               {
+                       struct in_addr  addr_obj;
+                       char *addr_str;
+
+                       int refclock_id = (ntohl (ptr->srcadr) >> 8) & 0x000000FF;
+
+                       if (refclock_id < refclock_names_num)
+                       {
+                               strncpy (peername, refclock_names[refclock_id],
+                                               sizeof (peername));
+                       }
+                       else
+                       {
+                               memset ((void *) &addr_obj, '\0', sizeof (addr_obj));
+                               addr_obj.s_addr = ptr->srcadr;
+                               addr_str = inet_ntoa (addr_obj);
+
+                               strncpy (peername, addr_str, sizeof (peername));
+                       }
+               }
+               else /* IPv4 */
+               {
+                       struct in_addr  addr_obj;
+                       struct hostent *addr_he;
+                       char           *addr_str;
+
+                       memset ((void *) &addr_obj, '\0', sizeof (addr_obj));
+                       addr_obj.s_addr = ptr->srcadr;
+                       addr_str = inet_ntoa (addr_obj);
+
+                       addr_he = gethostbyaddr ((const void *) &addr_obj,
+                                       sizeof (addr_obj), AF_INET);
+                       if (addr_he != NULL)
+                       {
+                               strncpy (peername, addr_he->h_name, sizeof (peername));
+                       }
+                       else
+                       {
+                               strncpy (peername, addr_str, sizeof (peername));
+                       }
+               }
+
                DBG ("peer %i:\n"
+                               "  peername   = %s\n"
                                "  srcadr     = 0x%08x\n"
                                "  delay      = %f\n"
                                "  offset_int = %i\n"
@@ -813,12 +933,15 @@ static void ntpd_read (void)
                                "  offset     = %f\n"
                                "  dispersion = %f\n",
                                i,
+                               peername,
                                ntohl (ptr->srcadr),
                                ntpd_read_fp (ptr->delay),
                                ntohl (ptr->offset_int),
                                ntohl (ptr->offset_frc),
                                offset,
                                ntpd_read_fp (ptr->dispersion));
+
+               ntpd_submit ("ntpd_time_offset", peername, offset);
        }
 
        free (ps);
@@ -835,6 +958,7 @@ void module_register (void)
        plugin_register (MODULE_NAME, ntpd_init, ntpd_read, NULL);
        plugin_register ("ntpd_time_offset", NULL, NULL, ntpd_write_time_offset);
        plugin_register ("ntpd_frequency_offset", NULL, NULL, ntpd_write_frequency_offset);
+       cf_register (MODULE_NAME, ntpd_config, config_keys, config_keys_num);
 }
 
 #undef MODULE_NAME