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