1*eabc0478Schristos /* $NetBSD: ntp_clockdev.c,v 1.2 2024/08/18 20:47:17 christos Exp $ */ 2897be3a4Schristos 3897be3a4Schristos /* ntp_clockdev.c - map clock instances to devices 4897be3a4Schristos * 5897be3a4Schristos * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. 6897be3a4Schristos * The contents of 'html/copyright.html' apply. 7897be3a4Schristos * --------------------------------------------------------------------- 8897be3a4Schristos * The runtime support for the 'device' configuration statement. Just a 9897be3a4Schristos * simple list to map refclock source addresses to the device(s) to use 10897be3a4Schristos * instead of the builtin names. 11897be3a4Schristos * --------------------------------------------------------------------- 12897be3a4Schristos */ 13897be3a4Schristos 14897be3a4Schristos #ifdef HAVE_CONFIG_H 15897be3a4Schristos # include <config.h> 16897be3a4Schristos #endif 17897be3a4Schristos 18897be3a4Schristos #ifdef HAVE_NETINFO 19897be3a4Schristos # include <netinfo/ni.h> 20897be3a4Schristos #endif 21897be3a4Schristos 22897be3a4Schristos #include <stdio.h> 23897be3a4Schristos #include <isc/net.h> 24897be3a4Schristos 25897be3a4Schristos #include "ntp.h" 26897be3a4Schristos #include "ntpd.h" 27897be3a4Schristos #include "ntp_clockdev.h" 28897be3a4Schristos 29897be3a4Schristos /* In the windows port 'refclock_open' is in 'libntp' (windows specific 30897be3a4Schristos * 'termios.c' source) and calling a function located in NTPD from the 31897be3a4Schristos * library is not something we should do. Therefore 'termios.c' now 32897be3a4Schristos * provides a hook to set a callback function used for the lookup, and 33897be3a4Schristos * we have to populate that when we have indeed device name 34897be3a4Schristos * redirections... 35897be3a4Schristos */ 36897be3a4Schristos #ifdef SYS_WINNT 37897be3a4Schristos extern const char * (*termios_device_lookup_func)(const sockaddr_u*, int); 38897be3a4Schristos #endif 39897be3a4Schristos 40897be3a4Schristos /* What we remember for a device redirection */ 41897be3a4Schristos typedef struct DeviceInfoS DeviceInfoT; 42897be3a4Schristos struct DeviceInfoS { 43897be3a4Schristos DeviceInfoT *next; /* link to next record */ 44897be3a4Schristos int ident; /* type (byte1) and unit (byte0)*/ 45897be3a4Schristos char *ttyName; /* time data IO device */ 46897be3a4Schristos char *ppsName; /* PPS device */ 47897be3a4Schristos }; 48897be3a4Schristos 49897be3a4Schristos /* Our list of device redirections: */ 50897be3a4Schristos static DeviceInfoT * InfoList = NULL; 51897be3a4Schristos 52897be3a4Schristos /* Free a single record: */ 53897be3a4Schristos static void freeDeviceInfo( 54897be3a4Schristos DeviceInfoT *item 55897be3a4Schristos ) 56897be3a4Schristos { 57897be3a4Schristos if (NULL != item) { 58897be3a4Schristos free(item->ttyName); 59897be3a4Schristos free(item->ppsName); 60897be3a4Schristos free(item); 61897be3a4Schristos } 62897be3a4Schristos } 63897be3a4Schristos 64897be3a4Schristos /* Get clock ID from pseudo network address. Returns -1 on error. */ 65897be3a4Schristos static int 66897be3a4Schristos getClockIdent( 67897be3a4Schristos const sockaddr_u *srcadr 68897be3a4Schristos ) 69897be3a4Schristos { 70897be3a4Schristos int clkType, clkUnit; 71897be3a4Schristos 72897be3a4Schristos /* 73897be3a4Schristos * Check for valid address and running peer 74897be3a4Schristos */ 75897be3a4Schristos if (!ISREFCLOCKADR(srcadr)) 76897be3a4Schristos return -1; 77897be3a4Schristos 78897be3a4Schristos clkType = REFCLOCKTYPE(srcadr); 79897be3a4Schristos clkUnit = REFCLOCKUNIT(srcadr); 80897be3a4Schristos return (clkType << 8) + clkUnit; 81897be3a4Schristos } 82897be3a4Schristos 83897be3a4Schristos /* Purge the complete redirection list. */ 84897be3a4Schristos void 85897be3a4Schristos clockdev_clear(void) 86897be3a4Schristos { 87897be3a4Schristos DeviceInfoT * item; 88897be3a4Schristos while (NULL != (item = InfoList)) { 89897be3a4Schristos InfoList = item->next; 90897be3a4Schristos freeDeviceInfo(item); 91897be3a4Schristos } 92897be3a4Schristos } 93897be3a4Schristos 94897be3a4Schristos /* Remove record(s) for a clock. 95897be3a4Schristos * returns number of removed records (maybe zero) or -1 on error 96897be3a4Schristos */ 97897be3a4Schristos int 98897be3a4Schristos clockdev_remove( 99897be3a4Schristos const sockaddr_u *addr_sock 100897be3a4Schristos ) 101897be3a4Schristos { 102897be3a4Schristos DeviceInfoT *item, **ppl; 103897be3a4Schristos int rcnt = 0; 104897be3a4Schristos const int ident = getClockIdent(addr_sock); 105897be3a4Schristos 106897be3a4Schristos if (ident < 0) 107897be3a4Schristos return -1; 108897be3a4Schristos 109897be3a4Schristos ppl = &InfoList; 110897be3a4Schristos while (NULL != (item = *ppl)) { 111897be3a4Schristos if (ident == item->ident) { 112897be3a4Schristos *ppl = item->next; 113897be3a4Schristos freeDeviceInfo(item); 114897be3a4Schristos ++rcnt; 115897be3a4Schristos } else { 116897be3a4Schristos ppl = &item->next; 117897be3a4Schristos } 118897be3a4Schristos } 119897be3a4Schristos return rcnt; 120897be3a4Schristos } 121897be3a4Schristos 122897be3a4Schristos /* Update or create a redirection record for a clock instace */ 123897be3a4Schristos int /*error*/ 124897be3a4Schristos clockdev_update( 125897be3a4Schristos const sockaddr_u *addr_sock, 126897be3a4Schristos const char *ttyName, 127897be3a4Schristos const char *ppsName 128897be3a4Schristos ) 129897be3a4Schristos { 130897be3a4Schristos DeviceInfoT *item; 131897be3a4Schristos const int ident = getClockIdent(addr_sock); 132897be3a4Schristos if (ident < 0) 133897be3a4Schristos return EINVAL; 134897be3a4Schristos 135897be3a4Schristos /* make sure Windows can use device redirections, too: */ 136897be3a4Schristos # ifdef SYS_WINNT 137897be3a4Schristos termios_device_lookup_func = clockdev_lookup; 138897be3a4Schristos # endif 139897be3a4Schristos 140897be3a4Schristos /* try to update an existing record */ 141897be3a4Schristos for (item = InfoList; NULL != item; item = item->next) 142897be3a4Schristos if (ident == item->ident) { 143897be3a4Schristos msyslog(LOG_INFO, "Update IO devices for %s: timedata='%s' ppsdata='%s'", 144897be3a4Schristos refnumtoa(addr_sock), 145897be3a4Schristos ttyName ? ttyName : "(null)", 146897be3a4Schristos ppsName ? ppsName : "(null)"); 147897be3a4Schristos free(item->ttyName); 148897be3a4Schristos free(item->ppsName); 149897be3a4Schristos item->ttyName = ttyName ? estrdup(ttyName) : NULL; 150897be3a4Schristos item->ppsName = ppsName ? estrdup(ppsName) : NULL; 151897be3a4Schristos return 0; 152897be3a4Schristos } 153897be3a4Schristos 154897be3a4Schristos /* seems we have to create a new entry... */ 155897be3a4Schristos msyslog(LOG_INFO, "Add IO devices for %s: timedata='%s' ppsdata='%s'", 156897be3a4Schristos refnumtoa(addr_sock), 157897be3a4Schristos ttyName ? ttyName : "(null)", 158897be3a4Schristos ppsName ? ppsName : "(null)"); 159897be3a4Schristos 160897be3a4Schristos item = emalloc(sizeof(*item)); 161897be3a4Schristos item->next = InfoList; 162897be3a4Schristos item->ident = ident; 163897be3a4Schristos item->ttyName = ttyName ? estrdup(ttyName) : NULL; 164897be3a4Schristos item->ppsName = ppsName ? estrdup(ppsName) : NULL; 165897be3a4Schristos InfoList = item; 166897be3a4Schristos return 0; 167897be3a4Schristos } 168897be3a4Schristos 169897be3a4Schristos /* Lookup a redirection for a clock instance. Returns either the name 170897be3a4Schristos * registered for the device or NULL if no redirection is found. 171897be3a4Schristos */ 172897be3a4Schristos const char* 173897be3a4Schristos clockdev_lookup( 174897be3a4Schristos const sockaddr_u *addr_sock, 175897be3a4Schristos int getPPS 176897be3a4Schristos ) 177897be3a4Schristos { 178897be3a4Schristos const DeviceInfoT *item; 179897be3a4Schristos const int ident = getClockIdent(addr_sock); 180897be3a4Schristos 181897be3a4Schristos if (ident < 0) 182897be3a4Schristos return NULL; 183897be3a4Schristos 184897be3a4Schristos for (item = InfoList; NULL != item; item = item->next) 185897be3a4Schristos if (ident == item->ident) 186897be3a4Schristos return getPPS ? item->ppsName : item->ttyName; 187897be3a4Schristos 188897be3a4Schristos return NULL; 189897be3a4Schristos } 190