static void free_res( restrict_u * res, int v6 ) { restrict_u ** plisthead; restrict_u * unlinked; restrictcount--; if (RES_LIMITED & res->flags) dec_res_limited(); if (v6) plisthead = &restrictlist6; else plisthead = &restrictlist4; UNLINK_SLIST(unlinked, *plisthead, res, link, restrict_u); NTP_INSIST(unlinked == res); if (v6) { zero_mem(res, V6_SIZEOF_RESTRICT_U); plisthead = &resfree6; } else { zero_mem(res, V4_SIZEOF_RESTRICT_U); plisthead = &resfree4; } LINK_SLIST(*plisthead, res, link); }
uint32_t caltontp( const struct calendar *jt ) { int32_t eraday; /* CE Rata Die number */ vint64 ntptime;/* resulting NTP time */ NTP_INSIST(jt != NULL); NTP_REQUIRE(jt->month <= 13); /* permit month 0..13! */ NTP_REQUIRE(jt->monthday <= 32); NTP_REQUIRE(jt->yearday <= 366); NTP_REQUIRE(jt->hour <= 24); NTP_REQUIRE(jt->minute <= MINSPERHR); NTP_REQUIRE(jt->second <= SECSPERMIN); /* * First convert the date to he corresponding RataDie * number. If yearday is not zero, assume that it contains a * useable value and avoid all calculations involving month * and day-of-month. Do a full evaluation otherwise. */ if (jt->yearday) eraday = ntpcal_year_to_ystart(jt->year) + jt->yearday - 1; else eraday = ntpcal_date_to_rd(jt); ntptime = ntpcal_dayjoin(eraday - DAY_NTP_STARTS, ntpcal_etime_to_seconds(jt->hour, jt->minute, jt->second)); return ntptime.d_s.lo; }
static restrict_u * match_restrict6_addr( const struct in6_addr * addr, u_short port ) { const int v6 = 1; restrict_u * res; restrict_u * next; struct in6_addr masked; for (res = restrictlist6; res != NULL; res = next) { next = res->link; NTP_INSIST(next != res); if (res->expire && res->expire <= current_time) free_res(res, v6); MASK_IPV6_ADDR(&masked, addr, &res->u.v6.mask); if (ADDR6_EQ(&masked, &res->u.v6.addr) && (!(RESM_NTPONLY & res->mflags) || NTP_PORT == (int)port)) break; } return res; }
/* * refclock_open - open serial port for reference clock * * This routine opens a serial port for I/O and sets default options. It * returns the file descriptor if success and zero if failure. */ int refclock_open( char *dev, /* device name pointer */ u_int speed, /* serial port speed (code) */ u_int lflags /* line discipline flags */ ) { int fd; int omode; #ifdef O_NONBLOCK char trash[128]; /* litter bin for old input data */ #endif /* * Open serial port and set default options */ omode = O_RDWR; #ifdef O_NONBLOCK omode |= O_NONBLOCK; #endif #ifdef O_NOCTTY omode |= O_NOCTTY; #endif fd = open(dev, omode, 0777); if (fd < 0) { msyslog(LOG_ERR, "refclock_open %s: %m", dev); return (0); } NTP_INSIST(fd != 0); if (!refclock_setup(fd, speed, lflags)) { close(fd); return (0); } if (!refclock_ioctl(fd, lflags)) { close(fd); return (0); } #ifdef O_NONBLOCK /* * We want to make sure there is no pending trash in the input * buffer. Since we have non-blocking IO available, this is a * good moment to read and dump all available outdated stuff * that might have become toxic for the driver. */ while (read(fd, trash, sizeof(trash)) > 0 || errno == EINTR) /*NOP*/; #endif return (fd); }
/* * getnetnum - given a host name, return its net number * and (optional) full name */ static int getnetnum( const char *hname, sockaddr_u *num, char *fullhost, int af ) { struct addrinfo hints, *ai = NULL; ZERO(hints); hints.ai_flags = AI_CANONNAME; #ifdef AI_ADDRCONFIG hints.ai_flags |= AI_ADDRCONFIG; #endif /* * decodenetnum only works with addresses, but handles syntax * that getaddrinfo doesn't: [2001::1]:1234 */ if (decodenetnum(hname, num)) { if (fullhost != NULL) getnameinfo(&num->sa, SOCKLEN(num), fullhost, LENHOSTNAME, NULL, 0, 0); return 1; } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) { NTP_INSIST(sizeof(*num) >= ai->ai_addrlen); memcpy(num, ai->ai_addr, ai->ai_addrlen); if (fullhost != NULL) { if (ai->ai_canonname != NULL) strlcpy(fullhost, ai->ai_canonname, LENHOSTNAME); else getnameinfo(&num->sa, SOCKLEN(num), fullhost, LENHOSTNAME, NULL, 0, 0); } return 1; } fprintf(stderr, "***Can't find host %s\n", hname); return 0; }
void caljulian( uint32_t ntp, struct calendar * jt ) { vint64 vlong; ntpcal_split split; NTP_INSIST(NULL != jt); /* * Unfold ntp time around current time into NTP domain. Split * into days and seconds, shift days into CE domain and * process the parts. */ vlong = ntpcal_ntp_to_ntp(ntp, NULL); split = ntpcal_daysplit(&vlong); ntpcal_daysplit_to_date(jt, &split, DAY_NTP_STARTS); }
static restrict_u * alloc_res6(void) { const size_t cb = V6_SIZEOF_RESTRICT_U; const size_t count = INC_RESLIST6; restrict_u * rl; restrict_u * res; int i; UNLINK_HEAD_SLIST(res, resfree6, link); if (res != NULL) return res; rl = emalloc_zero(count * cb); /* link all but the first onto free list */ res = (void *)((char *)rl + (count - 1) * cb); for (i = count - 1; i > 0; i--) { LINK_SLIST(resfree6, res, link); res = (void *)((char *)res - cb); } NTP_INSIST(rl == res); /* allocate the first */ return res; }
static struct tm * get_struct_tm( const vint64 *stamp, int local) { struct tm *tm = NULL; int32 folds = 0; time_t ts; #ifdef HAVE_INT64 int64 tl; ts = tl = stamp->q_s; /* * If there is chance of truncation, try to fix it. Let the * compiler find out if this can happen at all. */ while (ts != tl) { /* truncation? */ if (tl < 0) { if (--folds < MINFOLD) return NULL; tl += SOLAR_CYCLE_SECS; } else { if (++folds > MAXFOLD) return NULL; tl -= SOLAR_CYCLE_SECS; } ts = tl; /* next try... */ } #else /* * since we do not have 64-bit scalars, it's not likely we have * 64-bit time_t. Assume 32 bits and properly reduce the value. */ u_int32 hi, lo; hi = stamp->D_s.hi; lo = stamp->D_s.lo; while ((hi && ~hi) || ((hi ^ lo) & 0x80000000u)) { if (M_ISNEG(hi, lo)) { if (--folds < MINFOLD) return NULL; M_ADD(hi, lo, 0, SOLAR_CYCLE_SECS); } else { if (++folds > MAXFOLD) return NULL; M_SUB(hi, lo, 0, SOLAR_CYCLE_SECS); } } ts = (int32)lo; #endif /* * 'ts' should be a suitable value by now. Just go ahead, but * with care: * * There are some pathological implementations of 'gmtime()' * and 'localtime()' out there. No matter if we have 32-bit or * 64-bit 'time_t', try to fix this by solar cycle warping * again... * * At least the MSDN says that the (Microsoft) Windoze * versions of 'gmtime()' and 'localtime()' will bark on time * stamps < 0. */ while ((tm = (*(local ? localtime : gmtime))(&ts)) == NULL) if (ts < 0) { if (--folds < MINFOLD) return NULL; ts += SOLAR_CYCLE_SECS; } else if (ts >= (time_t)SOLAR_CYCLE_SECS) { if (++folds > MAXFOLD) return NULL; ts -= SOLAR_CYCLE_SECS; } else return NULL; /* That's truly pathological! */ /* 'tm' surely not NULL here! */ NTP_INSIST(tm != NULL); if (folds != 0) { tm->tm_year += folds * SOLAR_CYCLE_YEARS; if (tm->tm_year <= 0 || tm->tm_year >= 200) return NULL; /* left warp range... can't help here! */ } return tm; }
const char * socktohost( const sockaddr_u *sock ) { const char svc[] = "ntp"; char * pbuf; char * pliar; int gni_flags; struct addrinfo hints; struct addrinfo * alist; struct addrinfo * ai; sockaddr_u addr; size_t octets; int a_info; /* reverse the address to purported DNS name */ LIB_GETBUF(pbuf); gni_flags = NI_DGRAM | NI_NAMEREQD; if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH, NULL, 0, gni_flags)) return stoa(sock); /* use address */ TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf)); /* * Resolve the reversed name and make sure the reversed address * is among the results. */ ZERO(hints); hints.ai_family = AF(sock); hints.ai_protocol = IPPROTO_UDP; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = 0; alist = NULL; a_info = getaddrinfo(pbuf, svc, &hints, &alist); if (a_info == EAI_NONAME #ifdef EAI_NODATA || a_info == EAI_NODATA #endif ) { hints.ai_flags = AI_CANONNAME; #ifdef AI_ADDRCONFIG hints.ai_flags |= AI_ADDRCONFIG; #endif a_info = getaddrinfo(pbuf, svc, &hints, &alist); } #ifdef AI_ADDRCONFIG /* Some older implementations don't like AI_ADDRCONFIG. */ if (a_info == EAI_BADFLAGS) { hints.ai_flags &= ~AI_ADDRCONFIG; a_info = getaddrinfo(pbuf, svc, &hints, &alist); } #endif if (a_info) goto forward_fail; NTP_INSIST(alist != NULL); for (ai = alist; ai != NULL; ai = ai->ai_next) { /* * Make a convenience sockaddr_u copy from ai->ai_addr * because casting from sockaddr * to sockaddr_u * is * risking alignment problems on platforms where * sockaddr_u has stricter alignment than sockaddr, * such as sparc. */ ZERO_SOCK(&addr); octets = min(sizeof(addr), ai->ai_addrlen); memcpy(&addr, ai->ai_addr, octets); if (SOCK_EQ(sock, &addr)) break; } freeaddrinfo(alist); if (ai != NULL) return pbuf; /* forward check passed */ forward_fail: TRACE(1, ("%s forward check lookup fail: %s\n", pbuf, gai_strerror(a_info))); LIB_GETBUF(pliar); snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf); return pliar; }
/* * openhost - open a socket to a host */ static int openhost( const char *hname ) { char temphost[LENHOSTNAME]; int a_info, i; struct addrinfo hints, *ai = NULL; register const char *cp; char name[LENHOSTNAME]; char service[5]; /* * We need to get by the [] if they were entered */ cp = hname; if (*cp == '[') { cp++; for (i = 0; *cp && *cp != ']'; cp++, i++) name[i] = *cp; if (*cp == ']') { name[i] = '\0'; hname = name; } else { return 0; } } /* * First try to resolve it as an ip address and if that fails, * do a fullblown (dns) lookup. That way we only use the dns * when it is needed and work around some implementations that * will return an "IPv4-mapped IPv6 address" address if you * give it an IPv4 address to lookup. */ strcpy(service, "ntp"); memset((char *)&hints, 0, sizeof(struct addrinfo)); hints.ai_family = ai_fam_templ; hints.ai_protocol = IPPROTO_UDP; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_NUMERICHOST; a_info = getaddrinfo(hname, service, &hints, &ai); if (a_info == EAI_NONAME #ifdef EAI_NODATA || a_info == EAI_NODATA #endif ) { hints.ai_flags = AI_CANONNAME; #ifdef AI_ADDRCONFIG hints.ai_flags |= AI_ADDRCONFIG; #endif a_info = getaddrinfo(hname, service, &hints, &ai); } /* Some older implementations don't like AI_ADDRCONFIG. */ if (a_info == EAI_BADFLAGS) { hints.ai_flags = AI_CANONNAME; a_info = getaddrinfo(hname, service, &hints, &ai); } if (a_info != 0) { (void) fprintf(stderr, "%s\n", gai_strerror(a_info)); if (ai != NULL) freeaddrinfo(ai); return 0; } /* * getaddrinfo() has returned without error so ai should not * be NULL. */ NTP_INSIST(ai != NULL); if (ai->ai_canonname == NULL) { strncpy(temphost, stoa((sockaddr_u *)ai->ai_addr), LENHOSTNAME); temphost[LENHOSTNAME-1] = '\0'; } else { strncpy(temphost, ai->ai_canonname, LENHOSTNAME); temphost[LENHOSTNAME-1] = '\0'; } if (debug > 2) printf("Opening host %s\n", temphost); if (havehost == 1) { if (debug > 2) printf("Closing old host %s\n", currenthost); (void) closesocket(sockfd); havehost = 0; } (void) strcpy(currenthost, temphost); /* port maps to the same in both families */ s_port = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port; #ifdef SYS_VXWORKS ((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM); if (ai->ai_family == AF_INET) *(struct sockaddr_in *)&hostaddr= *((struct sockaddr_in *)ai->ai_addr); else *(struct sockaddr_in6 *)&hostaddr= *((struct sockaddr_in6 *)ai->ai_addr); #endif /* SYS_VXWORKS */ #ifdef SYS_WINNT { int optionValue = SO_SYNCHRONOUS_NONALERT; int err; err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue)); if (err != NO_ERROR) { (void) fprintf(stderr, "cannot open nonoverlapped sockets\n"); exit(1); } } sockfd = socket(ai->ai_family, SOCK_DGRAM, 0); if (sockfd == INVALID_SOCKET) { error("socket", "", ""); exit(-1); } #else sockfd = socket(ai->ai_family, SOCK_DGRAM, 0); if (sockfd == -1) error("socket", "", ""); #endif /* SYS_WINNT */ #ifdef NEED_RCVBUF_SLOP # ifdef SO_RCVBUF { int rbufsize = INITDATASIZE + 2048; /* 2K for slop */ if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rbufsize, sizeof(int)) == -1) error("setsockopt", "", ""); } # endif #endif #ifdef SYS_VXWORKS if (connect(sockfd, (struct sockaddr *)&hostaddr, sizeof(hostaddr)) == -1) #else if (connect(sockfd, (struct sockaddr *)ai->ai_addr, ai->ai_addrlen) == -1) #endif /* SYS_VXWORKS */ error("connect", "", ""); freeaddrinfo(ai); havehost = 1; req_pkt_size = REQ_LEN_NOMAC; impl_ver = IMPL_XNTPD; return 1; }
/* * hack_restrict - add/subtract/manipulate entries on the restrict list */ void hack_restrict( int op, sockaddr_u * resaddr, sockaddr_u * resmask, u_short mflags, u_short flags, u_long expire ) { int v6; restrict_u match; restrict_u * res; restrict_u ** plisthead; DPRINTF(1, ("restrict: op %d addr %s mask %s mflags %08x flags %08x\n", op, stoa(resaddr), stoa(resmask), mflags, flags)); if (NULL == resaddr) { NTP_REQUIRE(NULL == resmask); NTP_REQUIRE(RESTRICT_FLAGS == op); restrict_source_flags = flags; restrict_source_mflags = mflags; restrict_source_enabled = 1; return; } ZERO(match); /* silence VC9 potentially uninit warnings */ res = NULL; v6 = 0; if (IS_IPV4(resaddr)) { v6 = 0; /* * Get address and mask in host byte order for easy * comparison as u_int32 */ match.u.v4.addr = SRCADR(resaddr); match.u.v4.mask = SRCADR(resmask); match.u.v4.addr &= match.u.v4.mask; } else if (IS_IPV6(resaddr)) { v6 = 1; /* * Get address and mask in network byte order for easy * comparison as byte sequences (e.g. memcmp()) */ match.u.v6.mask = SOCK_ADDR6(resmask); MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr), &match.u.v6.mask); } else /* not IPv4 nor IPv6 */ NTP_REQUIRE(0); match.flags = flags; match.mflags = mflags; match.expire = expire; res = match_restrict_entry(&match, v6); switch (op) { case RESTRICT_FLAGS: /* * Here we add bits to the flags. If this is a * new restriction add it. */ if (NULL == res) { if (v6) { res = alloc_res6(); memcpy(res, &match, V6_SIZEOF_RESTRICT_U); plisthead = &restrictlist6; } else { res = alloc_res4(); memcpy(res, &match, V4_SIZEOF_RESTRICT_U); plisthead = &restrictlist4; } LINK_SORT_SLIST( *plisthead, res, (v6) ? res_sorts_before6(res, L_S_S_CUR()) : res_sorts_before4(res, L_S_S_CUR()), link, restrict_u); restrictcount++; if (RES_LIMITED & flags) inc_res_limited(); } else { if ((RES_LIMITED & flags) && !(RES_LIMITED & res->flags)) inc_res_limited(); res->flags |= flags; } break; case RESTRICT_UNFLAG: /* * Remove some bits from the flags. If we didn't * find this one, just return. */ if (res != NULL) { if ((RES_LIMITED & res->flags) && (RES_LIMITED & flags)) dec_res_limited(); res->flags &= ~flags; } break; case RESTRICT_REMOVE: case RESTRICT_REMOVEIF: /* * Remove an entry from the table entirely if we * found one. Don't remove the default entry and * don't remove an interface entry. */ if (res != NULL && (RESTRICT_REMOVEIF == op || !(RESM_INTERFACE & res->mflags)) && res != &restrict_def4 && res != &restrict_def6) free_res(res, v6); break; default: /* unknown op */ NTP_INSIST(0); break; } }
/* * decodenetnum convert text IP address and port to sockaddr_u * * Returns 0 for failure, 1 for success. */ int decodenetnum( const char *num, sockaddr_u *netnum ) { struct addrinfo hints, *ai = NULL; int err; u_short port; const char *cp; const char *port_str; char *pp; char *np; char name[80]; NTP_REQUIRE(num != NULL); NTP_REQUIRE(strlen(num) < sizeof(name)); port_str = NULL; if ('[' != num[0]) { /* * to distinguish IPv6 embedded colons from a port * specification on an IPv4 address, assume all * legal IPv6 addresses have at least two colons. */ pp = strchr(num, ':'); if (NULL == pp) cp = num; /* no colons */ else if (NULL != strchr(pp + 1, ':')) cp = num; /* two or more colons */ else { /* one colon */ strlcpy(name, num, sizeof(name)); cp = name; pp = strchr(cp, ':'); *pp = '\0'; port_str = pp + 1; } } else { cp = num + 1; np = name; while (*cp && ']' != *cp) *np++ = *cp++; *np = 0; if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2]) port_str = &cp[2]; cp = name; } ZERO(hints); hints.ai_flags = Z_AI_NUMERICHOST; err = getaddrinfo(cp, "ntp", &hints, &ai); if (err != 0) return 0; NTP_INSIST(ai->ai_addrlen <= sizeof(*netnum)); ZERO(*netnum); memcpy(netnum, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai); if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port)) port = NTP_PORT; SET_PORT(netnum, port); return 1; }
/* * Juergen Perlinger, 2008-11-12 * Add support for full calendar calculatios. If the day-of-year is provided * (that is, not zero) it will be used instead of month and day-of-month; * otherwise a full turn through the calendar calculations will be taken. * * I know that Harlan Stenn likes to see assertions in production code, and I * agree there, but it would be a tricky thing here. The algorithm is quite * capable of producing sensible answers even to seemingly weird inputs: the * date <any year here>-03-00, the 0.th March of the year, will be automtically * treated as the last day of February, no matter whether the year is a leap * year or not. So adding constraints is merely for the benefit of the callers, * because the only thing we can check for consistency is our input, produced * by somebody else. * * BTW: A total roundtrip using 'caljulian' would be a quite shaky thing: * Because of the truncation of the NTP time stamp to 32 bits and the epoch * unfolding around the current time done by 'caljulian' the roundtrip does * *not* necessarily reproduce the input, especially if the time spec is more * than 68 years off from the current time... */ u_long caltontp( const struct calendar *jt ) { ntp_u_int32_t days; /* full days in NTP epoch */ ntp_u_int32_t years; /* complete ACE years before date */ ntp_u_int32_t month; /* adjusted month for calendar */ NTP_INSIST(jt != NULL); NTP_REQUIRE(jt->month <= 13); /* permit month 0..13! */ NTP_REQUIRE(jt->monthday <= 32); NTP_REQUIRE(jt->yearday <= 366); NTP_REQUIRE(jt->hour <= 24); NTP_REQUIRE(jt->minute <= MINSPERHR); NTP_REQUIRE(jt->second <= SECSPERMIN); /* * First convert the date to fully elapsed days since NTP epoch. The * expressions used here give us initially days since 0001-01-01, the * beginning of the christian era in the proleptic gregorian calendar; * they are rebased on-the-fly into days since beginning of the NTP * epoch, 1900-01-01. */ if (jt->yearday) { /* * Assume that the day-of-year contains a useable value and * avoid all calculations involving month and day-of-month. */ years = jt->year - 1; days = years * DAYSPERYEAR /* days in previous years */ + years / 4 /* plus prior years's leap days */ - years / 100 /* minus leapless century years */ + years / 400 /* plus leapful Gregorian yrs */ + jt->yearday /* days this year */ - DAY_NTP_STARTS; /* rebase to NTP epoch */ } else { /* * The following code is according to the excellent book * 'Calendrical Calculations' by Nachum Dershowitz and Edward * Reingold. It does a full calendar evaluation, using one of * the alternate algorithms: Shift to a hypothetical year * starting on the previous march,1st; merge years, month and * days; undo the the 9 month shift (which is 306 days). The * advantage is that we do NOT need to now whether a year is a * leap year or not, because the leap day is the LAST day of * the year. */ month = (ntp_u_int32_t)jt->month + 9; years = jt->year - 1 + month / 12; month %= 12; days = years * DAYSPERYEAR /* days in previous years */ + years / 4 /* plus prior years's leap days */ - years / 100 /* minus leapless century years */ + years / 400 /* plus leapful Gregorian yrs */ + (month * 153 + 2) / 5 /* plus days before month */ + jt->monthday /* plus day-of-month */ - 306 /* minus 9 months */ - DAY_NTP_STARTS; /* rebase to NTP epoch */ } /* * Do the obvious: Merge everything together, making sure integer * promotion doesn't play dirty tricks on us; there is probably some * redundancy in the casts, but this drives it home with force. All * arithmetic is done modulo 2**32, because the result is truncated * anyway. */ return days * SECSPERDAY + (ntp_u_int32_t)jt->hour * MINSPERHR*SECSPERMIN + (ntp_u_int32_t)jt->minute * SECSPERMIN + (ntp_u_int32_t)jt->second; }