Coverage Report

Created: 2026-02-26 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntp-dev/ntpd/ntp_clockdev.c
Line
Count
Source
1
/* ntp_clockdev.c - map clock instances to devices
2
 *
3
 * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
4
 * The contents of 'html/copyright.html' apply.
5
 * ---------------------------------------------------------------------
6
 * The runtime support for the 'device' configuration statement.  Just a
7
 * simple list to map refclock source addresses to the device(s) to use
8
 * instead of the builtin names.
9
 * ---------------------------------------------------------------------
10
 */
11
12
#ifdef HAVE_CONFIG_H
13
# include <config.h>
14
#endif
15
16
#ifdef HAVE_NETINFO
17
# include <netinfo/ni.h>
18
#endif
19
20
#include <stdio.h>
21
#include <isc/net.h>
22
23
#include "ntp.h"
24
#include "ntpd.h"
25
#include "ntp_clockdev.h"
26
27
/* In the windows port 'refclock_open' is in 'libntp' (windows specific
28
 * 'termios.c' source) and calling a function located in NTPD from the
29
 * library is not something we should do.  Therefore 'termios.c' now
30
 * provides a hook to set a callback function used for the lookup, and
31
 * we have to populate that when we have indeed device name
32
 * redirections...
33
 */
34
#ifdef SYS_WINNT
35
extern const char * (*termios_device_lookup_func)(const sockaddr_u*, int);
36
#endif
37
38
/* What we remember for a device redirection */
39
typedef struct DeviceInfoS DeviceInfoT;
40
struct DeviceInfoS {
41
  DeviceInfoT *next;  /* link to next record    */
42
  int      ident; /* type (byte1) and unit (byte0)*/
43
  char      *ttyName; /* time data IO device    */
44
  char      *ppsName; /* PPS device     */
45
};
46
47
/* Our list of device redirections: */
48
static DeviceInfoT * InfoList = NULL;
49
50
/* Free a single record: */
51
static void freeDeviceInfo(
52
  DeviceInfoT *item
53
  )
54
0
{
55
0
  if (NULL != item) {
56
0
    free(item->ttyName);
57
0
    free(item->ppsName);
58
0
    free(item);
59
0
  }
60
0
}
61
62
/* Get clock ID from pseudo network address. Returns -1 on error. */
63
static int
64
getClockIdent(
65
  const sockaddr_u *srcadr
66
  )
67
0
{
68
0
  int clkType, clkUnit;
69
70
  /*
71
   * Check for valid address and running peer
72
   */
73
0
  if (!ISREFCLOCKADR(srcadr))
74
0
    return -1;
75
76
0
  clkType = REFCLOCKTYPE(srcadr);
77
0
  clkUnit = REFCLOCKUNIT(srcadr);
78
0
  return (clkType << 8) + clkUnit;
79
0
}
80
81
/* Purge the complete redirection list. */
82
void
83
clockdev_clear(void)
84
0
{
85
0
  DeviceInfoT * item;
86
0
  while (NULL != (item = InfoList)) {
87
0
    InfoList = item->next;
88
0
    freeDeviceInfo(item);
89
0
  }
90
0
}
91
92
/* Remove record(s) for a clock.
93
 * returns number of removed records (maybe zero) or -1 on error
94
 */
95
int
96
clockdev_remove(
97
  const sockaddr_u *addr_sock
98
  )
99
0
{
100
0
  DeviceInfoT *item, **ppl;
101
0
  int      rcnt  = 0;
102
0
  const int    ident = getClockIdent(addr_sock);
103
104
0
  if (ident < 0)
105
0
    return -1;
106
107
0
  ppl = &InfoList;
108
0
  while (NULL != (item = *ppl)) {
109
0
    if (ident == item->ident) {
110
0
      *ppl = item->next;
111
0
      freeDeviceInfo(item);
112
0
      ++rcnt;
113
0
    } else {
114
0
      ppl = &item->next;
115
0
    }
116
0
  }
117
0
  return rcnt;
118
0
}
119
120
/* Update or create a redirection record for a clock instace */
121
int /*error*/
122
clockdev_update(
123
  const sockaddr_u *addr_sock,
124
  const char   *ttyName,
125
  const char   *ppsName
126
  )
127
0
{
128
0
  DeviceInfoT *item;
129
0
  const int   ident = getClockIdent(addr_sock);
130
0
  if (ident < 0)
131
0
    return EINVAL;
132
133
  /* make sure Windows can use device redirections, too: */
134
#   ifdef SYS_WINNT
135
  termios_device_lookup_func = clockdev_lookup;
136
#   endif
137
138
  /* try to update an existing record */
139
0
  for (item = InfoList;  NULL != item;  item = item->next)
140
0
    if (ident == item->ident) {
141
0
      msyslog(LOG_INFO, "Update IO devices for %s: timedata='%s' ppsdata='%s'",
142
0
        refnumtoa(addr_sock),
143
0
        ttyName ? ttyName : "(null)",
144
0
        ppsName ? ppsName : "(null)");
145
0
      free(item->ttyName);
146
0
      free(item->ppsName);
147
0
      item->ttyName = ttyName ? estrdup(ttyName) : NULL;
148
0
      item->ppsName = ppsName ? estrdup(ppsName) : NULL;
149
0
      return 0;
150
0
    }
151
152
  /* seems we have to create a new entry... */
153
0
  msyslog(LOG_INFO, "Add IO devices for %s: timedata='%s' ppsdata='%s'",
154
0
    refnumtoa(addr_sock),
155
0
    ttyName ? ttyName : "(null)",
156
0
    ppsName ? ppsName : "(null)");
157
158
0
  item = emalloc(sizeof(*item));
159
0
  item->next    = InfoList;
160
0
  item->ident   = ident;
161
0
  item->ttyName = ttyName ? estrdup(ttyName) : NULL;
162
0
  item->ppsName = ppsName ? estrdup(ppsName) : NULL;
163
0
  InfoList = item;
164
0
  return 0;
165
0
}
166
167
/* Lookup a redirection for a clock instance. Returns either the name
168
 * registered for the device or NULL if no redirection is found.
169
 */
170
const char*
171
clockdev_lookup(
172
  const sockaddr_u *addr_sock,
173
  int     getPPS
174
  )
175
0
{
176
0
  const DeviceInfoT *item;
177
0
  const int   ident = getClockIdent(addr_sock);
178
179
0
  if (ident < 0)
180
0
    return NULL;
181
182
0
  for (item = InfoList;  NULL != item;  item = item->next)
183
0
    if (ident == item->ident)
184
0
      return getPPS ? item->ppsName : item->ttyName;
185
186
0
  return NULL;
187
0
}