summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpdate/ntpdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/ntpdate/ntpdate.c')
-rw-r--r--contrib/ntp/ntpdate/ntpdate.c625
1 files changed, 364 insertions, 261 deletions
diff --git a/contrib/ntp/ntpdate/ntpdate.c b/contrib/ntp/ntpdate/ntpdate.c
index b2cbe7e..a0a90ce 100644
--- a/contrib/ntp/ntpdate/ntpdate.c
+++ b/contrib/ntp/ntpdate/ntpdate.c
@@ -21,6 +21,12 @@
#include "ntp_select.h"
#include "ntp_stdlib.h"
+/* Don't include ISC's version of IPv6 variables and structures */
+#define ISC_IPV6_H 1
+#include "isc/net.h"
+#include "isc/result.h"
+#include "isc/sockaddr.h"
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -32,7 +38,6 @@
# include <poll.h>
#endif
#ifndef SYS_WINNT
-# include <netdb.h>
# ifdef HAVE_SYS_SIGNAL_H
# include <sys/signal.h>
# else
@@ -48,10 +53,6 @@
#include <arpa/inet.h>
-#ifdef __QNXNTO__
-# include "adjtime.h"
-#endif
-
#ifdef SYS_VXWORKS
# include "ioLib.h"
# include "sockLib.h"
@@ -59,6 +60,12 @@
/* select wants a zero structure ... */
struct timeval timeout = {0,0};
+#elif defined(SYS_WINNT)
+/*
+ * Windows does not abort a select select call if SIGALRM goes off
+ * so a 200 ms timeout is needed
+ */
+struct timeval timeout = {0,1000000/TIMER_HZ};
#else
struct timeval timeout = {60,0};
#endif
@@ -71,11 +78,13 @@ struct timeval timeout = {60,0};
#ifdef SYS_WINNT
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
-#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
#define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy
on Windows NT timers. */
#pragma comment(lib, "winmm")
+isc_boolean_t ntp_port_inuse(int af, u_short port);
+UINT wTimerRes;
#endif /* SYS_WINNT */
/*
@@ -96,14 +105,19 @@ static timer_t ntpdate_timerid;
* Compatibility stuff for Version 2
*/
#define NTP_MAXSKW 0x28f /* 0.01 sec in fp format */
-#define NTP_MINDIST 0x51f /* 0.02 sec in fp format */
+#define NTP_MINDIST 0x51f /* 0.02 sec in fp format */
#define PEER_MAXDISP (64*FP_SECOND) /* maximum dispersion (fp 64) */
#define NTP_INFIN 15 /* max stratum, infinity a la Bellman-Ford */
#define NTP_MAXWGT (8*FP_SECOND) /* maximum select weight 8 seconds */
-#define NTP_MAXLIST 5 /* maximum select list size */
+#define NTP_MAXLIST 5 /* maximum select list size */
#define PEER_SHIFT 8 /* 8 suitable for crystal time base */
/*
+ * for get_systime()
+ */
+s_char sys_precision; /* local clock precision (log2 s) */
+
+/*
* Debugging flag
*/
volatile int debug = 0;
@@ -113,14 +127,14 @@ volatile int debug = 0;
*/
int ai_fam_templ;
-int nbsock;
-SOCKET fd[MAX_AF]; /* support up to 2 sockets */
+int nbsock; /* the number of sockets used */
+SOCKET fd[MAX_AF];
int fd_family[MAX_AF]; /* to remember the socket family */
#ifdef HAVE_POLL_H
struct pollfd fdmask[MAX_AF];
#else
fd_set fdmask;
-int maxfd;
+SOCKET maxfd;
#endif
int polltest = 0;
@@ -141,16 +155,11 @@ volatile int alarm_flag = 0;
int simple_query = 0;
/*
- * Unpriviledged port flag.
+ * Unprivileged port flag.
*/
int unpriv_port = 0;
/*
- * Time to spend measuring drift rate
- */
-int rate = 0;
-
-/*
* Program name.
*/
char *progname;
@@ -202,7 +211,7 @@ int verbose = 0;
int always_step = 0;
int never_step = 0;
-int ntpdatemain P((int, char **));
+int ntpdatemain P((int, char **));
static void transmit P((struct server *));
static void receive P((struct recvbuf *));
@@ -212,7 +221,7 @@ static struct server *clock_select P((void));
static int clock_adjust P((void));
static void addserver P((char *));
static struct server *findserver P((struct sockaddr_storage *));
- void timer P((void));
+void timer P((void));
static void init_alarm P((void));
#ifndef SYS_WINNT
static RETSIGTYPE alarming P((int));
@@ -229,7 +238,7 @@ static void printserver P((struct server *, FILE *));
#ifdef SYS_WINNT
int on = 1;
WORD wVersionRequested;
-WSADATA wsaData;
+WSADATA wsaData;
HANDLE TimerThreadHandle = NULL;
#endif /* SYS_WINNT */
@@ -261,15 +270,11 @@ void clear_globals()
simple_query = 0;
/*
- * Unpriviledged port flag.
+ * Unprivileged port flag.
*/
unpriv_port = 0;
/*
- * Time to spend measuring drift rate
- */
- rate = 0;
- /*
* Systemwide parameters and flags
*/
sys_numservers = 0; /* number of servers to poll */
@@ -319,12 +324,12 @@ ntpdatemain (
)
{
int was_alarmed;
- struct recvbuf *rbuflist;
+ int tot_recvbufs;
struct recvbuf *rbuf;
l_fp tmp;
int errflg;
int c;
- int nfound;
+ int nfound;
#ifdef HAVE_NETINFO
ni_namelist *netinfoservers;
@@ -350,6 +355,12 @@ ntpdatemain (
clear_globals();
#endif
+
+ /* Check to see if we have IPv6. Otherwise force the -4 flag */
+ if (isc_net_probeipv6() != ISC_R_SUCCESS) {
+ ai_fam_templ = AF_INET;
+ }
+
errflg = 0;
progname = argv[0];
syslogit = 0;
@@ -357,7 +368,7 @@ ntpdatemain (
/*
* Decode argument list
*/
- while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qr:st:uv")) != EOF)
+ while ((c = ntp_getopt(argc, argv, "46a:bBde:k:o:p:qst:uv")) != EOF)
switch (c)
{
case '4':
@@ -413,17 +424,6 @@ ntpdatemain (
case 'q':
simple_query = 1;
break;
- case 'r':
- c = atoi(ntp_optarg);
- if (c <= 0 || c > (60 * 60)) {
- (void) fprintf(stderr,
- "%s: rate (%d) is invalid: 0 - %d\n",
- progname, c, (60 * 60));
- errflg++;
- } else {
- rate = c;
- }
- break;
case 's':
syslogit = 1;
break;
@@ -455,7 +455,7 @@ ntpdatemain (
if (errflg) {
(void) fprintf(stderr,
- "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-r rate] [-t timeo] server ...\n",
+ "usage: %s [-46bBdqsuv] [-a key#] [-e delay] [-k file] [-p samples] [-o version#] [-t timeo] server ...\n",
progname);
exit(2);
}
@@ -463,7 +463,12 @@ ntpdatemain (
if (debug || simple_query) {
#ifdef HAVE_SETVBUF
static char buf[BUFSIZ];
+#ifdef SYS_WINNT
+ /* Win32 does not implement line buffering */
+ setvbuf(stdout, NULL, _IONBF, BUFSIZ);
+#else
setvbuf(stdout, buf, _IOLBF, BUFSIZ);
+#endif /* SYS_WINNT */
#else
setlinebuf(stdout);
#endif
@@ -536,10 +541,8 @@ ntpdatemain (
}
authtrust(sys_authkey, 1);
if (!authistrusted(sys_authkey)) {
- char buf[10];
-
- (void) sprintf(buf, "%lu", (unsigned long)sys_authkey);
- msyslog(LOG_ERR, "authentication key %s unknown", buf);
+ msyslog(LOG_ERR, "authentication key %lu unknown",
+ (unsigned long) sys_authkey);
exit(1);
}
}
@@ -569,45 +572,41 @@ ntpdatemain (
initializing = 0;
was_alarmed = 0;
- rbuflist = (struct recvbuf *)0;
while (complete_servers < sys_numservers) {
#ifdef HAVE_POLL_H
- struct pollfd* rdfdes;
- rdfdes = fdmask;
+ struct pollfd* rdfdes;
+ rdfdes = fdmask;
#else
fd_set rdfdes;
- rdfdes = fdmask;
+ rdfdes = fdmask;
#endif
if (alarm_flag) { /* alarmed? */
was_alarmed = 1;
alarm_flag = 0;
}
- rbuflist = getrecvbufs(); /* get received buffers */
+ tot_recvbufs = full_recvbuffs(); /* get received buffers */
- if (!was_alarmed && rbuflist == (struct recvbuf *)0) {
+ if (!was_alarmed && tot_recvbufs == 0) {
/*
* Nothing to do. Wait for something.
*/
#ifdef HAVE_POLL_H
- nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000);
+ nfound = poll(rdfdes, (unsigned int)nbsock, timeout.tv_sec * 1000);
#else
- nfound = select(maxfd, &rdfdes, (fd_set *)0,
+ nfound = select(maxfd, &rdfdes, (fd_set *)0,
(fd_set *)0, &timeout);
#endif
if (nfound > 0)
input_handler();
- else if (
-#ifndef SYS_WINNT
- nfound == -1
-#else
- nfound == SOCKET_ERROR
-#endif /* SYS_WINNT */
- ) {
+ else if (nfound == SOCKET_ERROR)
+ {
#ifndef SYS_WINNT
if (errno != EINTR)
+#else
+ if (WSAGetLastError() != WSAEINTR)
#endif
netsyslog(LOG_ERR,
#ifdef HAVE_POLL_H
@@ -616,7 +615,7 @@ ntpdatemain (
"select() error: %m"
#endif
);
- } else {
+ } else if (errno != 0) {
#ifndef SYS_VXWORKS
netsyslog(LOG_DEBUG,
#ifdef HAVE_POLL_H
@@ -631,18 +630,19 @@ ntpdatemain (
was_alarmed = 1;
alarm_flag = 0;
}
- rbuflist = getrecvbufs(); /* get received buffers */
+ tot_recvbufs = full_recvbuffs(); /* get received buffers */
}
/*
* Out here, signals are unblocked. Call receive
* procedure for each incoming packet.
*/
- while (rbuflist != (struct recvbuf *)0) {
- rbuf = rbuflist;
- rbuflist = rbuf->next;
+ rbuf = get_full_recv_buffer();
+ while (rbuf != NULL)
+ {
receive(rbuf);
freerecvbuf(rbuf);
+ rbuf = get_full_recv_buffer();
}
/*
@@ -676,8 +676,8 @@ ntpdatemain (
/*
* transmit - transmit a packet to the given server, or mark it completed.
- * This is called by the timeout routine and by the receive
- * procedure.
+ * This is called by the timeout routine and by the receive
+ * procedure.
*/
static void
transmit(
@@ -710,7 +710,7 @@ transmit(
}
/*
- * If we're here, send another message to the server. Fill in
+ * If we're here, send another message to the server. Fill in
* the packet and let 'er rip.
*/
xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
@@ -779,7 +779,7 @@ receive(
int is_authentic;
if (debug)
- printf("receive(%s)\n", stoa(&rbufp->recv_srcadr));
+ printf("receive(%s)\n", stoa(&rbufp->recv_srcadr));
/*
* Check to see if the packet basically looks like something
* intended for us.
@@ -1060,29 +1060,29 @@ clock_select(void)
if (server->delay == 0) {
if (debug)
printf("%s: Server dropped: no data\n", ntoa(&server->srcadr));
- continue; /* no data */
+ continue; /* no data */
}
if (server->stratum > NTP_INFIN) {
if (debug)
printf("%s: Server dropped: strata too high\n", ntoa(&server->srcadr));
- continue; /* stratum no good */
+ continue; /* stratum no good */
}
if (server->delay > NTP_MAXWGT) {
if (debug)
printf("%s: Server dropped: server too far away\n",
- ntoa(&server->srcadr));
- continue; /* too far away */
+ ntoa(&server->srcadr));
+ continue; /* too far away */
}
if (server->leap == LEAP_NOTINSYNC) {
if (debug)
printf("%s: Server dropped: Leap not in sync\n", ntoa(&server->srcadr));
- continue; /* he's in trouble */
+ continue; /* he's in trouble */
}
if (!L_ISHIS(&server->org, &server->reftime)) {
if (debug)
printf("%s: Server dropped: server is very broken\n",
ntoa(&server->srcadr));
- continue; /* very broken host */
+ continue; /* very broken host */
}
if ((server->org.l_ui - server->reftime.l_ui)
>= NTP_MAXAGE) {
@@ -1239,7 +1239,7 @@ clock_select(void)
}
/*
- * That's it. Return our server.
+ * That's it. Return our server.
*/
return sys_server;
}
@@ -1283,7 +1283,7 @@ clock_adjust(void)
}
if (dostep) {
- if (simple_query || l_step_systime(&server->offset)) {
+ if (simple_query || debug || l_step_systime(&server->offset)){
msyslog(LOG_NOTICE, "step time server %s offset %s sec",
stoa(&server->srcadr),
lfptoa(&server->offset, 6));
@@ -1313,10 +1313,34 @@ clock_adjust(void)
}
+/*
+ * is_unreachable - check to see if we have a route to given destination
+ * (non-blocking).
+ */
+static int
+is_reachable (struct sockaddr_storage *dst)
+{
+ SOCKET sockfd;
+
+ sockfd = socket(dst->ss_family, SOCK_DGRAM, 0);
+ if (sockfd == -1) {
+ return 0;
+ }
+
+ if(connect(sockfd, (struct sockaddr *)dst, SOCKLEN(dst))) {
+ closesocket(sockfd);
+ return 0;
+ }
+ closesocket(sockfd);
+ return 1;
+}
+
+
+
/* XXX ELIMINATE: merge BIG slew into adj_systime in lib/systime.c */
/*
* addserver - determine a server's address and allocate a new structure
- * for it.
+ * for it.
*/
static void
addserver(
@@ -1324,54 +1348,69 @@ addserver(
)
{
register struct server *server;
- /* Address infos structure to store result of getaddrinfo */
- struct addrinfo *addrResult;
- /* Address infos structure to store hints for getaddrinfo */
- struct addrinfo hints;
- /* Error variable for getaddrinfo */
- int error;
- /* Service name */
- char service[5];
+ /* Address infos structure to store result of getaddrinfo */
+ struct addrinfo *addrResult, *ptr;
+ /* Address infos structure to store hints for getaddrinfo */
+ struct addrinfo hints;
+ /* Error variable for getaddrinfo */
+ int error;
+ /* Service name */
+ char service[5];
strcpy(service, "ntp");
- /* Get host address. Looking for UDP datagram connection. */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = ai_fam_templ;
- hints.ai_socktype = SOCK_DGRAM;
+ /* Get host address. Looking for UDP datagram connection. */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = ai_fam_templ;
+ hints.ai_socktype = SOCK_DGRAM;
#ifdef DEBUG
- if (debug)
- printf("Looking for host %s and service %s\n", serv, service);
+ if (debug)
+ printf("Looking for host %s and service %s\n", serv, service);
#endif
- error = getaddrinfo(serv, service, &hints, &addrResult);
- if (error != 0) {
- fprintf(stderr, "Error : %s\n", gai_strerror(error));
+ error = getaddrinfo(serv, service, &hints, &addrResult);
+ if (error != 0) {
+ /* Conduct more refined error analysis */
+ if (error == EAI_FAIL || error == EAI_AGAIN){
+ /* Name server is unusable. Exit after failing on the
+ first server, in order to shorten the timeout caused
+ by waiting for resolution of several servers */
+ fprintf(stderr, "Name server cannot be used, exiting");
+ msyslog(LOG_ERR, "name server cannot be used, reason: %s\n", gai_strerror(error));
+ exit(1);
+ }
+ fprintf(stderr, "Error : %s\n", gai_strerror(error));
msyslog(LOG_ERR, "can't find host %s\n", serv);
return;
}
#ifdef DEBUG
- else if (debug) {
- fprintf(stderr, "host found : %s\n", stohost((struct sockaddr_storage*)addrResult->ai_addr));
- }
+ else if (debug) {
+ fprintf(stderr, "host found : %s\n", stohost((struct sockaddr_storage*)addrResult->ai_addr));
+ }
#endif
- server = (struct server *)emalloc(sizeof(struct server));
- memset((char *)server, 0, sizeof(struct server));
-
- /* For now we only get the first returned server of the addrinfo list */
- memset(&(server->srcadr), 0, sizeof(struct sockaddr_storage));
- memcpy(&(server->srcadr), addrResult->ai_addr, addrResult->ai_addrlen);
- server->event_time = ++sys_numservers;
- if (sys_servers == NULL)
- sys_servers = server;
- else {
- struct server *sp;
+ /* We must get all returned server in case the first one fails */
+ for (ptr = addrResult; ptr != NULL; ptr = ptr->ai_next) {
+ if (is_reachable ((struct sockaddr_storage *)ptr->ai_addr)) {
+ server = (struct server *)emalloc(sizeof(struct server));
+ memset((char *)server, 0, sizeof(struct server));
+
+ memset(&(server->srcadr), 0, sizeof(struct sockaddr_storage));
+ memcpy(&(server->srcadr), ptr->ai_addr, ptr->ai_addrlen);
+ server->event_time = ++sys_numservers;
+ if (sys_servers == NULL)
+ sys_servers = server;
+ else {
+ struct server *sp;
- for (sp = sys_servers; sp->next_server != NULL;
- sp = sp->next_server) ;
- sp->next_server = server;
+ for (sp = sys_servers; sp->next_server != NULL;
+ sp = sp->next_server) ;
+ sp->next_server = server;
+ }
+ }
}
+
+ freeaddrinfo(addrResult);
}
@@ -1386,6 +1425,16 @@ findserver(
{
struct server *server;
struct server *mc_server;
+ isc_sockaddr_t laddr;
+ isc_sockaddr_t saddr;
+
+ if(addr->ss_family == AF_INET) {
+ isc_sockaddr_fromin( &laddr, &((struct sockaddr_in*)addr)->sin_addr, 0);
+ }
+ else {
+ isc_sockaddr_fromin6(&laddr, &((struct sockaddr_in6*)addr)->sin6_addr, 0);
+ }
+
mc_server = NULL;
if (htons(((struct sockaddr_in*)addr)->sin_port) != NTP_PORT)
@@ -1394,21 +1443,19 @@ findserver(
for (server = sys_servers; server != NULL;
server = server->next_server) {
- if (memcmp(addr, &server->srcadr, SOCKLEN(addr))==0)
+ if(server->srcadr.ss_family == AF_INET) {
+ isc_sockaddr_fromin(&saddr, &((struct sockaddr_in*)&server->srcadr)->sin_addr, 0);
+ }
+ else {
+ isc_sockaddr_fromin6(&saddr, &((struct sockaddr_in6*)&server->srcadr)->sin6_addr, 0);
+ }
+ if (isc_sockaddr_eqaddr(&laddr, &saddr) == ISC_TRUE)
return server;
- /* Multicast compatibility to verify here... I'm not sure it's working */
- if(addr->ss_family == AF_INET) {
- if (IN_MULTICAST(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)))
- mc_server = server;
- }
- else {
-#ifdef AF_INET6
- if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)(&server->srcadr))->sin6_addr))
- mc_server = server;
-#else
- return 0;
-#endif
- }
+
+ if(addr->ss_family == server->srcadr.ss_family) {
+ if (isc_sockaddr_ismulticast(&saddr) == ISC_TRUE)
+ mc_server = server;
+ }
}
if (mc_server != NULL) {
@@ -1423,7 +1470,7 @@ findserver(
server = (struct server *)emalloc(sizeof(struct server));
memset((char *)server, 0, sizeof(struct server));
- memcpy(&server->srcadr, &addr, sizeof(struct sockaddr_storage));
+ memcpy(&server->srcadr, addr, sizeof(struct sockaddr_storage));
server->event_time = ++sys_numservers;
@@ -1488,6 +1535,16 @@ alarming(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
#endif /* SYS_WINNT */
+#ifdef SYS_WINNT
+static void
+callTimeEndPeriod(void)
+{
+ timeEndPeriod( wTimerRes );
+ wTimerRes = 0;
+}
+#endif /* SYS_WINNT */
+
+
/*
* init_alarm - set up the timer interrupt
*/
@@ -1502,7 +1559,7 @@ init_alarm(void)
# endif
#else
TIMECAPS tc;
- UINT wTimerRes, wTimerID;
+ UINT wTimerID;
# endif /* SYS_WINNT */
#if defined SYS_CYGWIN32 || defined SYS_WINNT
HANDLE hToken;
@@ -1554,7 +1611,7 @@ init_alarm(void)
# endif
#if defined SYS_CYGWIN32
/*
- * Get previleges needed for fiddling with the clock
+ * Get privileges needed for fiddling with the clock
*/
/* get the current process token handle */
@@ -1564,7 +1621,7 @@ init_alarm(void)
}
/* get the LUID for system-time privilege. */
LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
- tkp.PrivilegeCount = 1; /* one privilege to set */
+ tkp.PrivilegeCount = 1; /* one privilege to set */
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
/* get set-time privilege for this process. */
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
@@ -1576,7 +1633,7 @@ init_alarm(void)
_tzset();
/*
- * Get previleges needed for fiddling with the clock
+ * Get privileges needed for fiddling with the clock
*/
/* get the current process token handle */
@@ -1586,7 +1643,7 @@ init_alarm(void)
}
/* get the LUID for system-time privilege. */
LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
- tkp.PrivilegeCount = 1; /* one privilege to set */
+ tkp.PrivilegeCount = 1; /* one privilege to set */
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
/* get set-time privilege for this process. */
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES) NULL, 0);
@@ -1609,14 +1666,15 @@ init_alarm(void)
wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
/* establish the minimum timer resolution that we'll use */
timeBeginPeriod(wTimerRes);
+ atexit(callTimeEndPeriod);
/* start the timer event */
wTimerID = timeSetEvent(
- (UINT) (1000/TIMER_HZ), /* Delay */
- wTimerRes, /* Resolution */
- (LPTIMECALLBACK) alarming, /* Callback function */
- (DWORD) dwUser, /* User data */
- TIME_PERIODIC); /* Event type (periodic) */
+ (UINT) (1000/TIMER_HZ), /* Delay */
+ wTimerRes, /* Resolution */
+ (LPTIMECALLBACK) alarming, /* Callback function */
+ (DWORD) dwUser, /* User data */
+ TIME_PERIODIC); /* Event type (periodic) */
if (wTimerID == 0) {
msyslog(LOG_ERR, "timeSetEvent failed: %m");
exit(1);
@@ -1647,10 +1705,11 @@ init_alarm(void)
static void
init_io(void)
{
- struct addrinfo *res, *ressave;
- struct addrinfo hints;
+ struct addrinfo *res, *ressave;
+ struct addrinfo hints;
char service[5];
- int optval = 1;
+ int optval = 1;
+ int check_ntp_port_in_use = !debug && !simple_query && !unpriv_port;
/*
* Init buffer free list and stat counters
@@ -1663,123 +1722,137 @@ init_io(void)
strcpy(service, "ntp");
- /*
- * Init hints addrinfo structure
- */
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_PASSIVE;
- hints.ai_socktype = SOCK_DGRAM;
-
- if(getaddrinfo(NULL, service, &hints, &res) != 0) {
- msyslog(LOG_ERR, "getaddrinfo() failed: %m");
- exit(1);
- /*NOTREACHED*/
- }
-
- /* Remember the address of the addrinfo structure chain */
- ressave = res;
-
- /*
- * For each structure returned, open and bind socket
- */
- for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) {
+ /*
+ * Init hints addrinfo structure
+ */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = ai_fam_templ;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if(getaddrinfo(NULL, service, &hints, &res) != 0) {
+ msyslog(LOG_ERR, "getaddrinfo() failed: %m");
+ exit(1);
+ /*NOTREACHED*/
+ }
+
+#ifdef SYS_WINNT
+ if (check_ntp_port_in_use && ntp_port_inuse(AF_INET, NTP_PORT)){
+ netsyslog(LOG_ERR, "the NTP socket is in use, exiting: %m");
+ exit(1);
+ }
+#endif
+
+ /* Remember the address of the addrinfo structure chain */
+ ressave = res;
+
+ /*
+ * For each structure returned, open and bind socket
+ */
+ for(nbsock = 0; (nbsock < MAX_AF) && res ; res = res->ai_next) {
/* create a datagram (UDP) socket */
- if ((fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {
+ fd[nbsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (fd[nbsock] == SOCKET_ERROR) {
+#ifndef SYS_WINNT
if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT ||
errno == EPFNOSUPPORT)
+#else
+ int err = WSAGetLastError();
+ if (err == WSAEPROTONOSUPPORT || err == WSAEAFNOSUPPORT ||
+ err == WSAEPFNOSUPPORT)
+#endif
continue;
netsyslog(LOG_ERR, "socket() failed: %m");
exit(1);
/*NOTREACHED*/
- }
- /* set socket to reuse address */
- if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) {
- netsyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m");
- exit(1);
- /*NOTREACHED*/
- }
+ }
+ /* set socket to reuse address */
+ if (setsockopt(fd[nbsock], SOL_SOCKET, SO_REUSEADDR, (void*) &optval, sizeof(optval)) < 0) {
+ netsyslog(LOG_ERR, "setsockopt() SO_REUSEADDR failed: %m");
+ exit(1);
+ /*NOTREACHED*/
+ }
#ifdef IPV6_V6ONLY
- /* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */
- if (res->ai_family == AF_INET6)
- if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) {
- netsyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m");
- exit(1);
- /*NOTREACHED*/
- }
+ /* Restricts AF_INET6 socket to IPv6 communications (see RFC 2553bis-03) */
+ if (res->ai_family == AF_INET6)
+ if (setsockopt(fd[nbsock], IPPROTO_IPV6, IPV6_V6ONLY, (void*) &optval, sizeof(optval)) < 0) {
+ netsyslog(LOG_ERR, "setsockopt() IPV6_V6ONLY failed: %m");
+ exit(1);
+ /*NOTREACHED*/
+ }
#endif
- /* Remember the socket family in fd_family structure */
- fd_family[nbsock] = res->ai_family;
+ /* Remember the socket family in fd_family structure */
+ fd_family[nbsock] = res->ai_family;
- /*
- * bind the socket to the NTP port
- */
- if (!debug && !simple_query && !unpriv_port) {
- if (bind(fd[nbsock], res->ai_addr, SOCKLEN(res->ai_addr)) < 0) {
+ /*
+ * bind the socket to the NTP port
+ */
+ if (check_ntp_port_in_use) {
+ if (bind(fd[nbsock], res->ai_addr, SOCKLEN(res->ai_addr)) < 0) {
#ifndef SYS_WINNT
- if (errno == EADDRINUSE)
+ if (errno == EADDRINUSE)
#else
if (WSAGetLastError() == WSAEADDRINUSE)
#endif /* SYS_WINNT */
- netsyslog(LOG_ERR,
- "the NTP socket is in use, exiting");
+ netsyslog(LOG_ERR, "the NTP socket is in use, exiting");
else
- netsyslog(LOG_ERR, "bind() fails: %m");
- exit(1);
+ netsyslog(LOG_ERR, "bind() fails: %m");
+ exit(1);
+ }
}
- }
#ifdef HAVE_POLL_H
- fdmask[nbsock].fd = fd[nbsock];
- fdmask[nbsock].events = POLLIN;
+ fdmask[nbsock].fd = fd[nbsock];
+ fdmask[nbsock].events = POLLIN;
#else
- FD_SET(fd[nbsock], &fdmask);
- if ((SOCKET) maxfd < fd[nbsock]+1) {
- maxfd = fd[nbsock]+1;
- }
+ FD_SET(fd[nbsock], &fdmask);
+ if (maxfd < fd[nbsock]+1) {
+ maxfd = fd[nbsock]+1;
+ }
#endif
- /*
- * set non-blocking,
- */
+ /*
+ * set non-blocking,
+ */
#ifndef SYS_WINNT
# ifdef SYS_VXWORKS
- {
- int on = TRUE;
+ {
+ int on = TRUE;
- if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) {
- netsyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
- exit(1);
- }
- }
+ if (ioctl(fd[nbsock],FIONBIO, &on) == ERROR) {
+ netsyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
+ exit(1);
+ }
+ }
# else /* not SYS_VXWORKS */
# if defined(O_NONBLOCK)
- if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) {
- netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
- exit(1);
- /*NOTREACHED*/
- }
+ if (fcntl(fd[nbsock], F_SETFL, O_NONBLOCK) < 0) {
+ netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
+ exit(1);
+ /*NOTREACHED*/
+ }
# else /* not O_NONBLOCK */
# if defined(FNDELAY)
- if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) {
- netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
- exit(1);
- /*NOTREACHED*/
- }
+ if (fcntl(fd[nbsock], F_SETFL, FNDELAY) < 0) {
+ netsyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails: %m");
+ exit(1);
+ /*NOTREACHED*/
+ }
# else /* FNDELAY */
# include "Bletch: Need non blocking I/O"
# endif /* FNDELAY */
# endif /* not O_NONBLOCK */
# endif /* SYS_VXWORKS */
#else /* SYS_WINNT */
- if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) {
- netsyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
- exit(1);
- }
+ if (ioctlsocket(fd[nbsock], FIONBIO, (u_long *) &on) == SOCKET_ERROR) {
+ netsyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
+ exit(1);
+ }
#endif /* SYS_WINNT */
- nbsock++;
- }
- freeaddrinfo(ressave);
+ nbsock++;
+ }
+ freeaddrinfo(ressave);
}
/*
@@ -1792,40 +1865,39 @@ sendpkt(
int len
)
{
- int i;
+ int i;
int cc;
- SOCKET sock = 0;
+ SOCKET sock = INVALID_SOCKET;
#ifdef SYS_WINNT
DWORD err;
#endif /* SYS_WINNT */
- /* Find a local family compatible socket to send ntp packet to ntp server */
- for(i = 0; (i < MAX_AF); i++) {
- if(dest->ss_family == fd_family[i]) {
- sock = fd[i];
- break;
- }
- }
+ /* Find a local family compatible socket to send ntp packet to ntp server */
+ for(i = 0; (i < MAX_AF); i++) {
+ if(dest->ss_family == fd_family[i]) {
+ sock = fd[i];
+ break;
+ }
+ }
- if ( sock == 0 ) {
- netsyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet");
- exit(1);
- /*NOTREACHED*/
- }
+ if ( sock == INVALID_SOCKET ) {
+ netsyslog(LOG_ERR, "cannot find family compatible socket to send ntp packet");
+ exit(1);
+ /*NOTREACHED*/
+ }
cc = sendto(sock, (char *)pkt, len, 0, (struct sockaddr *)dest,
SOCKLEN(dest));
+ if (cc == SOCKET_ERROR) {
#ifndef SYS_WINNT
- if (cc == -1) {
if (errno != EWOULDBLOCK && errno != ENOBUFS)
#else
- if (cc == SOCKET_ERROR) {
err = WSAGetLastError();
if (err != WSAEWOULDBLOCK && err != WSAENOBUFS)
#endif /* SYS_WINNT */
- netsyslog(LOG_ERR, "sendto(%s): %m", stohost(dest));
+ netsyslog(LOG_ERR, "sendto(%s): %m", stohost(dest));
}
}
@@ -1841,13 +1913,13 @@ input_handler(void)
struct timeval tvzero;
int fromlen;
l_fp ts;
- int i;
+ int i;
#ifdef HAVE_POLL_H
struct pollfd fds[MAX_AF];
#else
fd_set fds;
#endif
- int fdc = 0;
+ int fdc = 0;
/*
* Do a poll to see if we have data
@@ -1856,33 +1928,33 @@ input_handler(void)
tvzero.tv_sec = tvzero.tv_usec = 0;
#ifdef HAVE_POLL_H
memcpy(fds, fdmask, sizeof(fdmask));
- n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000);
+ n = poll(fds, (unsigned int)nbsock, tvzero.tv_sec * 1000);
- /*
- * Determine which socket received data
- */
+ /*
+ * Determine which socket received data
+ */
- for(i=0; i < nbsock; i++) {
- if(fds[i].revents & POLLIN) {
- fdc = fd[i];
- break;
- }
- }
+ for(i=0; i < nbsock; i++) {
+ if(fds[i].revents & POLLIN) {
+ fdc = fd[i];
+ break;
+ }
+ }
#else
fds = fdmask;
- n = select(maxfd, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
+ n = select(maxfd, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
- /*
- * Determine which socket received data
- */
+ /*
+ * Determine which socket received data
+ */
- for(i=0; i < maxfd; i++) {
- if(FD_ISSET(fd[i], &fds)) {
- fdc = fd[i];
- break;
- }
- }
+ for(i=0; i < nbsock; i++) {
+ if(FD_ISSET(fd[i], &fds)) {
+ fdc = fd[i];
+ break;
+ }
+ }
#endif
@@ -2057,7 +2129,7 @@ l_step_systime(
l_adj_systime(ts);
return 1;
#endif
-#else /* SLEWALWAYS */
+#else /* SLEWALWAYS */
if (debug)
return 1;
LFPTOD(ts, dtemp);
@@ -2223,3 +2295,34 @@ getnetinfoservers(void)
return(namelist);
}
#endif
+
+#ifdef SYS_WINNT
+isc_boolean_t ntp_port_inuse(int af, u_short port)
+{
+ /*
+ * Check if NTP socket is already in use on this system
+ * This is only for Windows Systems, as they tend not to fail on the real bind() below
+ */
+
+ SOCKET checksocket;
+ struct sockaddr_in checkservice;
+ checksocket = socket(af, SOCK_DGRAM, 0);
+ if (checksocket == INVALID_SOCKET) {
+ return (ISC_TRUE);
+ }
+
+ checkservice.sin_family = (short) AF_INET;
+ checkservice.sin_addr.s_addr = INADDR_LOOPBACK;
+ checkservice.sin_port = htons(port);
+
+ if (bind(checksocket, (struct sockaddr *)&checkservice,
+ sizeof(checkservice)) == SOCKET_ERROR) {
+ if ( WSAGetLastError() == WSAEADDRINUSE ){
+ closesocket(checksocket);
+ return (ISC_TRUE);
+ }
+ }
+ closesocket(checksocket);
+ return (ISC_FALSE);
+}
+#endif
OpenPOWER on IntegriCloud