diff options
Diffstat (limited to 'contrib/ntp/ntpd/ntp_clockdev.c')
-rw-r--r-- | contrib/ntp/ntpd/ntp_clockdev.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/contrib/ntp/ntpd/ntp_clockdev.c b/contrib/ntp/ntpd/ntp_clockdev.c new file mode 100644 index 000000000000..312cebd5a666 --- /dev/null +++ b/contrib/ntp/ntpd/ntp_clockdev.c @@ -0,0 +1,187 @@ +/* ntp_clockdev.c - map clock instances to devices + * + * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. + * The contents of 'html/copyright.html' apply. + * --------------------------------------------------------------------- + * The runtime support for the 'device' configuration statement. Just a + * simple list to map refclock source addresses to the device(s) to use + * instead of the builtin names. + * --------------------------------------------------------------------- + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_NETINFO +# include <netinfo/ni.h> +#endif + +#include <stdio.h> +#include <isc/net.h> + +#include "ntp.h" +#include "ntpd.h" +#include "ntp_clockdev.h" + +/* In the windows port 'refclock_open' is in 'libntp' (windows specific + * 'termios.c' source) and calling a function located in NTPD from the + * library is not something we should do. Therefore 'termios.c' now + * provides a hook to set a callback function used for the lookup, and + * we have to populate that when we have indeed device name + * redirections... + */ +#ifdef SYS_WINNT +extern const char * (*termios_device_lookup_func)(const sockaddr_u*, int); +#endif + +/* What we remember for a device redirection */ +typedef struct DeviceInfoS DeviceInfoT; +struct DeviceInfoS { + DeviceInfoT *next; /* link to next record */ + int ident; /* type (byte1) and unit (byte0)*/ + char *ttyName; /* time data IO device */ + char *ppsName; /* PPS device */ +}; + +/* Our list of device redirections: */ +static DeviceInfoT * InfoList = NULL; + +/* Free a single record: */ +static void freeDeviceInfo( + DeviceInfoT *item + ) +{ + if (NULL != item) { + free(item->ttyName); + free(item->ppsName); + free(item); + } +} + +/* Get clock ID from pseudo network address. Returns -1 on error. */ +static int +getClockIdent( + const sockaddr_u *srcadr + ) +{ + int clkType, clkUnit; + + /* + * Check for valid address and running peer + */ + if (!ISREFCLOCKADR(srcadr)) + return -1; + + clkType = REFCLOCKTYPE(srcadr); + clkUnit = REFCLOCKUNIT(srcadr); + return (clkType << 8) + clkUnit; +} + +/* Purge the complete redirection list. */ +void +clockdev_clear(void) +{ + DeviceInfoT * item; + while (NULL != (item = InfoList)) { + InfoList = item->next; + freeDeviceInfo(item); + } +} + +/* Remove record(s) for a clock. + * returns number of removed records (maybe zero) or -1 on error + */ +int +clockdev_remove( + const sockaddr_u *addr_sock + ) +{ + DeviceInfoT *item, **ppl; + int rcnt = 0; + const int ident = getClockIdent(addr_sock); + + if (ident < 0) + return -1; + + ppl = &InfoList; + while (NULL != (item = *ppl)) { + if (ident == item->ident) { + *ppl = item->next; + freeDeviceInfo(item); + ++rcnt; + } else { + ppl = &item->next; + } + } + return rcnt; +} + +/* Update or create a redirection record for a clock instace */ +int /*error*/ +clockdev_update( + const sockaddr_u *addr_sock, + const char *ttyName, + const char *ppsName + ) +{ + DeviceInfoT *item; + const int ident = getClockIdent(addr_sock); + if (ident < 0) + return EINVAL; + + /* make sure Windows can use device redirections, too: */ +# ifdef SYS_WINNT + termios_device_lookup_func = clockdev_lookup; +# endif + + /* try to update an existing record */ + for (item = InfoList; NULL != item; item = item->next) + if (ident == item->ident) { + msyslog(LOG_INFO, "Update IO devices for %s: timedata='%s' ppsdata='%s'", + refnumtoa(addr_sock), + ttyName ? ttyName : "(null)", + ppsName ? ppsName : "(null)"); + free(item->ttyName); + free(item->ppsName); + item->ttyName = ttyName ? estrdup(ttyName) : NULL; + item->ppsName = ppsName ? estrdup(ppsName) : NULL; + return 0; + } + + /* seems we have to create a new entry... */ + msyslog(LOG_INFO, "Add IO devices for %s: timedata='%s' ppsdata='%s'", + refnumtoa(addr_sock), + ttyName ? ttyName : "(null)", + ppsName ? ppsName : "(null)"); + + item = emalloc(sizeof(*item)); + item->next = InfoList; + item->ident = ident; + item->ttyName = ttyName ? estrdup(ttyName) : NULL; + item->ppsName = ppsName ? estrdup(ppsName) : NULL; + InfoList = item; + return 0; +} + +/* Lookup a redirection for a clock instance. Returns either the name + * registered for the device or NULL if no redirection is found. + */ +const char* +clockdev_lookup( + const sockaddr_u *addr_sock, + int getPPS + ) +{ + const DeviceInfoT *item; + const int ident = getClockIdent(addr_sock); + + if (ident < 0) + return NULL; + + for (item = InfoList; NULL != item; item = item->next) + if (ident == item->ident) + return getPPS ? item->ppsName : item->ttyName; + + return NULL; +} |