/contrib/ntp/ntpd/ntp_util.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 801 lines · 542 code · 84 blank · 175 comment · 91 complexity · e3c99388bedd1787c8f517ed985fa470 MD5 · raw file

  1. /*
  2. * ntp_util.c - stuff I didn't have any other place for
  3. */
  4. #ifdef HAVE_CONFIG_H
  5. # include <config.h>
  6. #endif
  7. #include "ntpd.h"
  8. #include "ntp_io.h"
  9. #include "ntp_unixtime.h"
  10. #include "ntp_filegen.h"
  11. #include "ntp_if.h"
  12. #include "ntp_stdlib.h"
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <sys/types.h>
  16. #ifdef HAVE_SYS_IOCTL_H
  17. # include <sys/ioctl.h>
  18. #endif
  19. #ifdef HAVE_IEEEFP_H
  20. # include <ieeefp.h>
  21. #endif
  22. #ifdef HAVE_MATH_H
  23. # include <math.h>
  24. #endif
  25. #ifdef DOSYNCTODR
  26. # if !defined(VMS)
  27. # include <sys/resource.h>
  28. # endif /* VMS */
  29. #endif
  30. #if defined(VMS)
  31. # include <descrip.h>
  32. #endif /* VMS */
  33. /*
  34. * This contains odds and ends. Right now the only thing you'll find
  35. * in here is the hourly stats printer and some code to support
  36. * rereading the keys file, but I may eventually put other things in
  37. * here such as code to do something with the leap bits.
  38. */
  39. /*
  40. * Name of the keys file
  41. */
  42. static char *key_file_name;
  43. /*
  44. * The name of the drift_comp file and the temporary.
  45. */
  46. static char *stats_drift_file;
  47. static char *stats_temp_file;
  48. int stats_write_period = 3600; /* # of seconds between writes. */
  49. double stats_write_tolerance = 0;
  50. static double prev_drift_comp = 99999.;
  51. /*
  52. * Statistics file stuff
  53. */
  54. #ifndef NTP_VAR
  55. # ifndef SYS_WINNT
  56. # define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */
  57. # else
  58. # define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */
  59. # endif /* SYS_WINNT */
  60. #endif
  61. #ifndef MAXPATHLEN
  62. # define MAXPATHLEN 256
  63. #endif
  64. static char statsdir[MAXPATHLEN] = NTP_VAR;
  65. static FILEGEN peerstats;
  66. static FILEGEN loopstats;
  67. static FILEGEN clockstats;
  68. static FILEGEN rawstats;
  69. static FILEGEN sysstats;
  70. #ifdef DEBUG_TIMING
  71. static FILEGEN timingstats;
  72. #endif
  73. #ifdef OPENSSL
  74. static FILEGEN cryptostats;
  75. #endif /* OPENSSL */
  76. /*
  77. * This controls whether stats are written to the fileset. Provided
  78. * so that ntpdc can turn off stats when the file system fills up.
  79. */
  80. int stats_control;
  81. /*
  82. * Initial frequency offset later passed to the loopfilter.
  83. */
  84. double old_drift;
  85. /*
  86. * init_util - initialize the utilities
  87. */
  88. void
  89. init_util(void)
  90. {
  91. stats_drift_file = 0;
  92. stats_temp_file = 0;
  93. key_file_name = 0;
  94. filegen_register(&statsdir[0], "peerstats", &peerstats);
  95. filegen_register(&statsdir[0], "loopstats", &loopstats);
  96. filegen_register(&statsdir[0], "clockstats", &clockstats);
  97. filegen_register(&statsdir[0], "rawstats", &rawstats);
  98. filegen_register(&statsdir[0], "sysstats", &sysstats);
  99. #ifdef OPENSSL
  100. filegen_register(&statsdir[0], "cryptostats", &cryptostats);
  101. #endif /* OPENSSL */
  102. #ifdef DEBUG_TIMING
  103. filegen_register(&statsdir[0], "timingstats", &timingstats);
  104. #endif
  105. }
  106. /*
  107. * hourly_stats - print some interesting stats
  108. */
  109. void
  110. write_stats(void)
  111. {
  112. FILE *fp;
  113. #ifdef DOSYNCTODR
  114. struct timeval tv;
  115. #if !defined(VMS)
  116. int prio_set;
  117. #endif
  118. #ifdef HAVE_GETCLOCK
  119. struct timespec ts;
  120. #endif
  121. int o_prio;
  122. /*
  123. * Sometimes having a Sun can be a drag.
  124. *
  125. * The kernel variable dosynctodr controls whether the system's
  126. * soft clock is kept in sync with the battery clock. If it
  127. * is zero, then the soft clock is not synced, and the battery
  128. * clock is simply left to rot. That means that when the system
  129. * reboots, the battery clock (which has probably gone wacky)
  130. * sets the soft clock. That means ntpd starts off with a very
  131. * confused idea of what time it is. It then takes a large
  132. * amount of time to figure out just how wacky the battery clock
  133. * has made things drift, etc, etc. The solution is to make the
  134. * battery clock sync up to system time. The way to do THAT is
  135. * to simply set the time of day to the current time of day, but
  136. * as quickly as possible. This may, or may not be a sensible
  137. * thing to do.
  138. *
  139. * CAVEAT: settimeofday() steps the sun clock by about 800 us,
  140. * so setting DOSYNCTODR seems a bad idea in the
  141. * case of us resolution
  142. */
  143. #if !defined(VMS)
  144. /* (prr) getpriority returns -1 on error, but -1 is also a valid
  145. * return value (!), so instead we have to zero errno before the
  146. * call and check it for non-zero afterwards.
  147. */
  148. errno = 0;
  149. prio_set = 0;
  150. o_prio = getpriority(PRIO_PROCESS,0); /* Save setting */
  151. /*
  152. * (prr) if getpriority succeeded, call setpriority to raise
  153. * scheduling priority as high as possible. If that succeeds
  154. * as well, set the prio_set flag so we remember to reset
  155. * priority to its previous value below. Note that on Solaris
  156. * 2.6 (and beyond?), both getpriority and setpriority will fail
  157. * with ESRCH, because sched_setscheduler (called from main) put
  158. * us in the real-time scheduling class which setpriority
  159. * doesn't know about. Being in the real-time class is better
  160. * than anything setpriority can do, anyhow, so this error is
  161. * silently ignored.
  162. */
  163. if ((errno == 0) && (setpriority(PRIO_PROCESS,0,-20) == 0))
  164. prio_set = 1; /* overdrive */
  165. #endif /* VMS */
  166. #ifdef HAVE_GETCLOCK
  167. (void) getclock(TIMEOFDAY, &ts);
  168. tv.tv_sec = ts.tv_sec;
  169. tv.tv_usec = ts.tv_nsec / 1000;
  170. #else /* not HAVE_GETCLOCK */
  171. GETTIMEOFDAY(&tv,(struct timezone *)NULL);
  172. #endif /* not HAVE_GETCLOCK */
  173. if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0) {
  174. msyslog(LOG_ERR, "can't sync battery time: %m");
  175. }
  176. #if !defined(VMS)
  177. if (prio_set)
  178. setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */
  179. #endif /* VMS */
  180. #endif /* DOSYNCTODR */
  181. NLOG(NLOG_SYSSTATIST)
  182. msyslog(LOG_INFO,
  183. "offset %.6f sec freq %.3f ppm error %.6f poll %d",
  184. last_offset, drift_comp * 1e6, sys_jitter,
  185. sys_poll);
  186. record_sys_stats();
  187. if ((u_long)(fabs(prev_drift_comp - drift_comp) * 1e9) <=
  188. (u_long)(fabs(stats_write_tolerance * drift_comp) * 1e9)) {
  189. return;
  190. }
  191. prev_drift_comp = drift_comp;
  192. if (stats_drift_file != 0) {
  193. if ((fp = fopen(stats_temp_file, "w")) == NULL) {
  194. msyslog(LOG_ERR, "can't open %s: %m",
  195. stats_temp_file);
  196. return;
  197. }
  198. fprintf(fp, "%.3f\n", drift_comp * 1e6);
  199. (void)fclose(fp);
  200. /* atomic */
  201. #ifdef SYS_WINNT
  202. (void) _unlink(stats_drift_file); /* rename semantics differ under NT */
  203. #endif /* SYS_WINNT */
  204. #ifndef NO_RENAME
  205. (void) rename(stats_temp_file, stats_drift_file);
  206. #else
  207. /* we have no rename NFS of ftp in use */
  208. if ((fp = fopen(stats_drift_file, "w")) == NULL) {
  209. msyslog(LOG_ERR, "can't open %s: %m",
  210. stats_drift_file);
  211. return;
  212. }
  213. #endif
  214. #if defined(VMS)
  215. /* PURGE */
  216. {
  217. $DESCRIPTOR(oldvers,";-1");
  218. struct dsc$descriptor driftdsc = {
  219. strlen(stats_drift_file),0,0,stats_drift_file };
  220. while(lib$delete_file(&oldvers,&driftdsc) & 1) ;
  221. }
  222. #endif
  223. }
  224. }
  225. /*
  226. * stats_config - configure the stats operation
  227. */
  228. void
  229. stats_config(
  230. int item,
  231. const char *invalue /* only one type so far */
  232. )
  233. {
  234. FILE *fp;
  235. const char *value;
  236. int len;
  237. /*
  238. * Expand environment strings under Windows NT, since the
  239. * command interpreter doesn't do this, the program must.
  240. */
  241. #ifdef SYS_WINNT
  242. char newvalue[MAX_PATH], parameter[MAX_PATH];
  243. if (!ExpandEnvironmentStrings(invalue, newvalue, MAX_PATH)) {
  244. switch(item) {
  245. case STATS_FREQ_FILE:
  246. strcpy(parameter,"STATS_FREQ_FILE");
  247. break;
  248. case STATS_STATSDIR:
  249. strcpy(parameter,"STATS_STATSDIR");
  250. break;
  251. case STATS_PID_FILE:
  252. strcpy(parameter,"STATS_PID_FILE");
  253. break;
  254. default:
  255. strcpy(parameter,"UNKNOWN");
  256. break;
  257. }
  258. value = invalue;
  259. msyslog(LOG_ERR,
  260. "ExpandEnvironmentStrings(%s) failed: %m\n", parameter);
  261. } else {
  262. value = newvalue;
  263. }
  264. #else
  265. value = invalue;
  266. #endif /* SYS_WINNT */
  267. switch(item) {
  268. case STATS_FREQ_FILE:
  269. if (stats_drift_file != 0) {
  270. (void) free(stats_drift_file);
  271. (void) free(stats_temp_file);
  272. stats_drift_file = 0;
  273. stats_temp_file = 0;
  274. }
  275. if (value == 0 || (len = strlen(value)) == 0)
  276. break;
  277. stats_drift_file = (char*)emalloc((u_int)(len + 1));
  278. #if !defined(VMS)
  279. stats_temp_file = (char*)emalloc((u_int)(len +
  280. sizeof(".TEMP")));
  281. #else
  282. stats_temp_file = (char*)emalloc((u_int)(len +
  283. sizeof("-TEMP")));
  284. #endif /* VMS */
  285. memmove(stats_drift_file, value, (unsigned)(len+1));
  286. memmove(stats_temp_file, value, (unsigned)len);
  287. #if !defined(VMS)
  288. memmove(stats_temp_file + len, ".TEMP",
  289. sizeof(".TEMP"));
  290. #else
  291. memmove(stats_temp_file + len, "-TEMP",
  292. sizeof("-TEMP"));
  293. #endif /* VMS */
  294. /*
  295. * Open drift file and read frequency. If the file is
  296. * missing or contains errors, tell the loop to reset.
  297. */
  298. if ((fp = fopen(stats_drift_file, "r")) == NULL) {
  299. old_drift = 1e9;
  300. break;
  301. }
  302. if (fscanf(fp, "%lf", &old_drift) != 1) {
  303. msyslog(LOG_ERR, "Frequency format error in %s",
  304. stats_drift_file);
  305. old_drift = 1e9;
  306. fclose(fp);
  307. break;
  308. }
  309. fclose(fp);
  310. prev_drift_comp = old_drift / 1e6;
  311. msyslog(LOG_INFO,
  312. "frequency initialized %.3f PPM from %s",
  313. old_drift, stats_drift_file);
  314. break;
  315. case STATS_STATSDIR:
  316. if (strlen(value) >= sizeof(statsdir)) {
  317. msyslog(LOG_ERR,
  318. "value for statsdir too long (>%d, sigh)",
  319. (int)sizeof(statsdir)-1);
  320. } else {
  321. l_fp now;
  322. get_systime(&now);
  323. strcpy(statsdir,value);
  324. if(peerstats.prefix == &statsdir[0] &&
  325. peerstats.fp != NULL) {
  326. fclose(peerstats.fp);
  327. peerstats.fp = NULL;
  328. filegen_setup(&peerstats, now.l_ui);
  329. }
  330. if(loopstats.prefix == &statsdir[0] &&
  331. loopstats.fp != NULL) {
  332. fclose(loopstats.fp);
  333. loopstats.fp = NULL;
  334. filegen_setup(&loopstats, now.l_ui);
  335. }
  336. if(clockstats.prefix == &statsdir[0] &&
  337. clockstats.fp != NULL) {
  338. fclose(clockstats.fp);
  339. clockstats.fp = NULL;
  340. filegen_setup(&clockstats, now.l_ui);
  341. }
  342. if(rawstats.prefix == &statsdir[0] &&
  343. rawstats.fp != NULL) {
  344. fclose(rawstats.fp);
  345. rawstats.fp = NULL;
  346. filegen_setup(&rawstats, now.l_ui);
  347. }
  348. if(sysstats.prefix == &statsdir[0] &&
  349. sysstats.fp != NULL) {
  350. fclose(sysstats.fp);
  351. sysstats.fp = NULL;
  352. filegen_setup(&sysstats, now.l_ui);
  353. }
  354. #ifdef OPENSSL
  355. if(cryptostats.prefix == &statsdir[0] &&
  356. cryptostats.fp != NULL) {
  357. fclose(cryptostats.fp);
  358. cryptostats.fp = NULL;
  359. filegen_setup(&cryptostats, now.l_ui);
  360. }
  361. #endif /* OPENSSL */
  362. }
  363. break;
  364. case STATS_PID_FILE:
  365. if ((fp = fopen(value, "w")) == NULL) {
  366. msyslog(LOG_ERR, "Can't open %s: %m", value);
  367. break;
  368. }
  369. fprintf(fp, "%d", (int) getpid());
  370. fclose(fp);;
  371. break;
  372. default:
  373. /* oh well */
  374. break;
  375. }
  376. }
  377. /*
  378. * record_peer_stats - write peer statistics to file
  379. *
  380. * file format:
  381. * day (mjd)
  382. * time (s past UTC midnight)
  383. * peer (ip address)
  384. * peer status word (hex)
  385. * peer offset (s)
  386. * peer delay (s)
  387. * peer error bound (s)
  388. * peer error (s)
  389. */
  390. void
  391. record_peer_stats(
  392. struct sockaddr_storage *addr,
  393. int status,
  394. double offset,
  395. double delay,
  396. double dispersion,
  397. double skew
  398. )
  399. {
  400. l_fp now;
  401. u_long day;
  402. if (!stats_control)
  403. return;
  404. get_systime(&now);
  405. filegen_setup(&peerstats, now.l_ui);
  406. day = now.l_ui / 86400 + MJD_1900;
  407. now.l_ui %= 86400;
  408. if (peerstats.fp != NULL) {
  409. fprintf(peerstats.fp,
  410. "%lu %s %s %x %.9f %.9f %.9f %.9f\n",
  411. day, ulfptoa(&now, 3), stoa(addr), status, offset,
  412. delay, dispersion, skew);
  413. fflush(peerstats.fp);
  414. }
  415. }
  416. /*
  417. * record_loop_stats - write loop filter statistics to file
  418. *
  419. * file format:
  420. * day (mjd)
  421. * time (s past midnight)
  422. * offset (s)
  423. * frequency (approx ppm)
  424. * time constant (log base 2)
  425. */
  426. void
  427. record_loop_stats(
  428. double offset,
  429. double freq,
  430. double jitter,
  431. double stability,
  432. int spoll
  433. )
  434. {
  435. l_fp now;
  436. u_long day;
  437. if (!stats_control)
  438. return;
  439. get_systime(&now);
  440. filegen_setup(&loopstats, now.l_ui);
  441. day = now.l_ui / 86400 + MJD_1900;
  442. now.l_ui %= 86400;
  443. if (loopstats.fp != NULL) {
  444. fprintf(loopstats.fp, "%lu %s %.9f %.3f %.9f %.6f %d\n",
  445. day, ulfptoa(&now, 3), offset, freq * 1e6, jitter,
  446. stability * 1e6, spoll);
  447. fflush(loopstats.fp);
  448. }
  449. }
  450. /*
  451. * record_clock_stats - write clock statistics to file
  452. *
  453. * file format:
  454. * day (mjd)
  455. * time (s past midnight)
  456. * peer (ip address)
  457. * text message
  458. */
  459. void
  460. record_clock_stats(
  461. struct sockaddr_storage *addr,
  462. const char *text
  463. )
  464. {
  465. l_fp now;
  466. u_long day;
  467. if (!stats_control)
  468. return;
  469. get_systime(&now);
  470. filegen_setup(&clockstats, now.l_ui);
  471. day = now.l_ui / 86400 + MJD_1900;
  472. now.l_ui %= 86400;
  473. if (clockstats.fp != NULL) {
  474. fprintf(clockstats.fp, "%lu %s %s %s\n",
  475. day, ulfptoa(&now, 3), stoa(addr), text);
  476. fflush(clockstats.fp);
  477. }
  478. }
  479. /*
  480. * record_raw_stats - write raw timestamps to file
  481. *
  482. *
  483. * file format
  484. * time (s past midnight)
  485. * peer ip address
  486. * local ip address
  487. * t1 t2 t3 t4 timestamps
  488. */
  489. void
  490. record_raw_stats(
  491. struct sockaddr_storage *srcadr,
  492. struct sockaddr_storage *dstadr,
  493. l_fp *t1,
  494. l_fp *t2,
  495. l_fp *t3,
  496. l_fp *t4
  497. )
  498. {
  499. l_fp now;
  500. u_long day;
  501. if (!stats_control)
  502. return;
  503. get_systime(&now);
  504. filegen_setup(&rawstats, now.l_ui);
  505. day = now.l_ui / 86400 + MJD_1900;
  506. now.l_ui %= 86400;
  507. if (rawstats.fp != NULL) {
  508. fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n",
  509. day, ulfptoa(&now, 3), stoa(srcadr), dstadr ? stoa(dstadr) : "-",
  510. ulfptoa(t1, 9), ulfptoa(t2, 9), ulfptoa(t3, 9),
  511. ulfptoa(t4, 9));
  512. fflush(rawstats.fp);
  513. }
  514. }
  515. /*
  516. * record_sys_stats - write system statistics to file
  517. *
  518. * file format
  519. * time (s past midnight)
  520. * time since startup (hr)
  521. * packets recieved
  522. * packets processed
  523. * current version
  524. * previous version
  525. * bad version
  526. * access denied
  527. * bad length or format
  528. * bad authentication
  529. * rate exceeded
  530. */
  531. void
  532. record_sys_stats(void)
  533. {
  534. l_fp now;
  535. u_long day;
  536. if (!stats_control)
  537. return;
  538. get_systime(&now);
  539. filegen_setup(&sysstats, now.l_ui);
  540. day = now.l_ui / 86400 + MJD_1900;
  541. now.l_ui %= 86400;
  542. if (sysstats.fp != NULL) {
  543. fprintf(sysstats.fp,
  544. "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
  545. day, ulfptoa(&now, 3), sys_stattime / 3600,
  546. sys_received, sys_processed, sys_newversionpkt,
  547. sys_oldversionpkt, sys_unknownversion,
  548. sys_restricted, sys_badlength, sys_badauth,
  549. sys_limitrejected);
  550. fflush(sysstats.fp);
  551. proto_clr_stats();
  552. }
  553. }
  554. #ifdef OPENSSL
  555. /*
  556. * record_crypto_stats - write crypto statistics to file
  557. *
  558. * file format:
  559. * day (mjd)
  560. * time (s past midnight)
  561. * peer (ip address)
  562. * text message
  563. */
  564. void
  565. record_crypto_stats(
  566. struct sockaddr_storage *addr,
  567. const char *text
  568. )
  569. {
  570. l_fp now;
  571. u_long day;
  572. if (!stats_control)
  573. return;
  574. get_systime(&now);
  575. filegen_setup(&cryptostats, now.l_ui);
  576. day = now.l_ui / 86400 + MJD_1900;
  577. now.l_ui %= 86400;
  578. if (cryptostats.fp != NULL) {
  579. if (addr == NULL)
  580. fprintf(cryptostats.fp, "%lu %s %s\n",
  581. day, ulfptoa(&now, 3), text);
  582. else
  583. fprintf(cryptostats.fp, "%lu %s %s %s\n",
  584. day, ulfptoa(&now, 3), stoa(addr), text);
  585. fflush(cryptostats.fp);
  586. }
  587. }
  588. #endif /* OPENSSL */
  589. #ifdef DEBUG_TIMING
  590. /*
  591. * record_crypto_stats - write crypto statistics to file
  592. *
  593. * file format:
  594. * day (mjd)
  595. * time (s past midnight)
  596. * text message
  597. */
  598. void
  599. record_timing_stats(
  600. const char *text
  601. )
  602. {
  603. static unsigned int flshcnt;
  604. l_fp now;
  605. u_long day;
  606. if (!stats_control)
  607. return;
  608. get_systime(&now);
  609. filegen_setup(&timingstats, now.l_ui);
  610. day = now.l_ui / 86400 + MJD_1900;
  611. now.l_ui %= 86400;
  612. if (timingstats.fp != NULL) {
  613. fprintf(timingstats.fp, "%lu %s %s\n",
  614. day, lfptoa(&now, 3), text);
  615. if (++flshcnt % 100 == 0)
  616. fflush(timingstats.fp);
  617. }
  618. }
  619. #endif
  620. /*
  621. * getauthkeys - read the authentication keys from the specified file
  622. */
  623. void
  624. getauthkeys(
  625. const char *keyfile
  626. )
  627. {
  628. int len;
  629. len = strlen(keyfile);
  630. if (len == 0)
  631. return;
  632. if (key_file_name != 0) {
  633. if (len > (int)strlen(key_file_name)) {
  634. (void) free(key_file_name);
  635. key_file_name = 0;
  636. }
  637. }
  638. if (key_file_name == 0) {
  639. #ifndef SYS_WINNT
  640. key_file_name = (char*)emalloc((u_int) (len + 1));
  641. #else
  642. key_file_name = (char*)emalloc((u_int) (MAXPATHLEN));
  643. #endif
  644. }
  645. #ifndef SYS_WINNT
  646. memmove(key_file_name, keyfile, (unsigned)(len+1));
  647. #else
  648. if (!ExpandEnvironmentStrings(keyfile, key_file_name, MAXPATHLEN))
  649. {
  650. msyslog(LOG_ERR,
  651. "ExpandEnvironmentStrings(KEY_FILE) failed: %m\n");
  652. }
  653. #endif /* SYS_WINNT */
  654. authreadkeys(key_file_name);
  655. }
  656. /*
  657. * rereadkeys - read the authentication key file over again.
  658. */
  659. void
  660. rereadkeys(void)
  661. {
  662. if (key_file_name != 0)
  663. authreadkeys(key_file_name);
  664. }
  665. /*
  666. * sock_hash - hash an sockaddr_storage structure
  667. */
  668. int
  669. sock_hash(
  670. struct sockaddr_storage *addr
  671. )
  672. {
  673. int hashVal;
  674. int i;
  675. int len;
  676. char *ch;
  677. hashVal = 0;
  678. len = 0;
  679. /*
  680. * We can't just hash the whole thing because there are hidden
  681. * fields in sockaddr_in6 that might be filled in by recvfrom(),
  682. * so just use the family, port and address.
  683. */
  684. ch = (char *)&addr->ss_family;
  685. hashVal = 37 * hashVal + (int)*ch;
  686. if (sizeof(addr->ss_family) > 1) {
  687. ch++;
  688. hashVal = 37 * hashVal + (int)*ch;
  689. }
  690. switch(addr->ss_family) {
  691. case AF_INET:
  692. ch = (char *)&((struct sockaddr_in *)addr)->sin_addr;
  693. len = sizeof(struct in_addr);
  694. break;
  695. case AF_INET6:
  696. ch = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
  697. len = sizeof(struct in6_addr);
  698. break;
  699. }
  700. for (i = 0; i < len ; i++)
  701. hashVal = 37 * hashVal + (int)*(ch + i);
  702. hashVal = hashVal % 128; /* % MON_HASH_SIZE hardcoded */
  703. if (hashVal < 0)
  704. hashVal += 128;
  705. return hashVal;
  706. }
  707. #if notyet
  708. /*
  709. * ntp_exit - document explicitly that ntpd has exited
  710. */
  711. void
  712. ntp_exit(int retval)
  713. {
  714. msyslog(LOG_ERR, "EXITING with return code %d", retval);
  715. exit(retval);
  716. }
  717. #endif