Source code pulled from OpenBSD for OpenNTPD. The place to contribute to this code is via the OpenBSD CVS tree.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
4.8 KiB

  1. /* $OpenBSD: sensors.c,v 1.19 2006/06/02 21:17:01 henning Exp $ */
  2. /*
  3. * Copyright (c) 2006 Henning Brauer <henning@openbsd.org>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
  14. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  15. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/param.h>
  18. #include <sys/queue.h>
  19. #include <sys/sensors.h>
  20. #include <sys/sysctl.h>
  21. #include <sys/device.h>
  22. #include <sys/hotplug.h>
  23. #include <errno.h>
  24. #include <fcntl.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <unistd.h>
  28. #include "ntpd.h"
  29. #define SENSORS_MAX 255
  30. #define _PATH_DEV_HOTPLUG "/dev/hotplug"
  31. void sensor_probe(int);
  32. void sensor_add(struct sensor *);
  33. void sensor_remove(struct ntp_sensor *);
  34. struct ntpd_conf *conf;
  35. void
  36. sensor_init(struct ntpd_conf *c)
  37. {
  38. conf = c;
  39. TAILQ_INIT(&conf->ntp_sensors);
  40. }
  41. void
  42. sensor_scan(void)
  43. {
  44. int i;
  45. for (i = 0; i < SENSORS_MAX; i++)
  46. sensor_probe(i);
  47. }
  48. void
  49. sensor_probe(int id)
  50. {
  51. int mib[3];
  52. size_t len;
  53. struct sensor sensor;
  54. mib[0] = CTL_HW;
  55. mib[1] = HW_SENSORS;
  56. mib[2] = id;
  57. len = sizeof(sensor);
  58. if (sysctl(mib, 3, &sensor, &len, NULL, 0) == -1) {
  59. if (errno != ENOENT)
  60. log_warn("sensor_probe sysctl");
  61. return;
  62. }
  63. if (sensor.type == SENSOR_TIMEDELTA)
  64. sensor_add(&sensor);
  65. }
  66. void
  67. sensor_add(struct sensor *sensor)
  68. {
  69. struct ntp_sensor *s;
  70. struct ntp_conf_sensor *cs;
  71. /* check wether it is already there */
  72. TAILQ_FOREACH(s, &conf->ntp_sensors, entry)
  73. if (!strcmp(s->device, sensor->device))
  74. return;
  75. /* check wether it is requested in the config file */
  76. for (cs = TAILQ_FIRST(&conf->ntp_conf_sensors); cs != NULL &&
  77. strcmp(cs->device, sensor->device) && strcmp(cs->device, "*");
  78. cs = TAILQ_NEXT(cs, entry))
  79. ; /* nothing */
  80. if (cs == NULL)
  81. return;
  82. if ((s = calloc(1, sizeof(*s))) == NULL)
  83. fatal("sensor_add calloc");
  84. s->next = time(NULL);
  85. s->weight = cs->weight;
  86. if ((s->device = strdup(sensor->device)) == NULL)
  87. fatal("sensor_add strdup");
  88. s->sensorid = sensor->num;
  89. TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry);
  90. log_debug("sensor %s added", s->device);
  91. }
  92. void
  93. sensor_remove(struct ntp_sensor *s)
  94. {
  95. TAILQ_REMOVE(&conf->ntp_sensors, s, entry);
  96. free(s->device);
  97. free(s);
  98. }
  99. void
  100. sensor_query(struct ntp_sensor *s)
  101. {
  102. struct sensor sensor;
  103. u_int32_t refid;
  104. int mib[3];
  105. size_t len;
  106. s->next = time(NULL) + SENSOR_QUERY_INTERVAL;
  107. if (s->update.rcvd < time(NULL) - SENSOR_DATA_MAXAGE)
  108. s->update.good = 0;
  109. mib[0] = CTL_HW;
  110. mib[1] = HW_SENSORS;
  111. mib[2] = s->sensorid;
  112. len = sizeof(sensor);
  113. if (sysctl(mib, 3, &sensor, &len, NULL, 0) == -1) {
  114. if (errno == ENOENT)
  115. sensor_remove(s);
  116. else
  117. log_warn("sensor_query sysctl");
  118. return;
  119. }
  120. if (sensor.flags & SENSOR_FINVALID ||
  121. sensor.status != SENSOR_S_OK)
  122. return;
  123. if (sensor.type != SENSOR_TIMEDELTA ||
  124. strcmp(sensor.device, s->device)) {
  125. sensor_remove(s);
  126. return;
  127. }
  128. if (sensor.tv.tv_sec == s->update.rcvd) /* already seen */
  129. return;
  130. memcpy(&refid, "HARD", sizeof(refid));
  131. s->update.status.refid = htonl(refid);
  132. s->update.offset = 0 - (float)sensor.value / 1000000000.0;
  133. s->update.status.stratum = 0; /* increased when sent out */
  134. s->update.status.rootdelay = 0;
  135. s->update.status.rootdispersion = 0;
  136. s->update.status.reftime = sensor.tv.tv_sec;
  137. s->update.rcvd = sensor.tv.tv_sec;
  138. s->update.good = 1;
  139. log_debug("sensor %s: offset %f", s->device, s->update.offset);
  140. }
  141. int
  142. sensor_hotplugfd(void)
  143. {
  144. #ifdef notyet
  145. int fd, flags;
  146. if ((fd = open(_PATH_DEV_HOTPLUG, O_RDONLY, 0)) == -1) {
  147. log_warn("open %s", _PATH_DEV_HOTPLUG);
  148. return (-1);
  149. }
  150. if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
  151. fatal("fnctl F_GETFL");
  152. flags |= O_NONBLOCK;
  153. if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
  154. fatal("fnctl F_SETFL");
  155. return (fd);
  156. #else
  157. return (-1);
  158. #endif
  159. }
  160. void
  161. sensor_hotplugevent(int fd)
  162. {
  163. struct hotplug_event he;
  164. ssize_t n;
  165. do {
  166. if ((n = read(fd, &he, sizeof(he))) == -1 &&
  167. errno != EINTR && errno != EAGAIN)
  168. fatal("sensor_hotplugevent read");
  169. if (n == sizeof(he))
  170. switch (he.he_type) {
  171. case HOTPLUG_DEVAT:
  172. if (he.he_devclass == DV_DULL &&
  173. !strcmp(he.he_devname, "sensor"))
  174. sensor_scan();
  175. break;
  176. default: /* ignore */
  177. break;
  178. }
  179. else if (n > 0)
  180. fatal("sensor_hotplugevent: short read");
  181. } while (n > 0 || (n == -1 && errno == EINTR));
  182. }