/* * mon_start - start up the monitoring software */ void mon_start( int mode ) { size_t octets; u_int min_hash_slots; if (MON_OFF == mode) /* MON_OFF is 0 */ return; if (mon_enabled) { mon_enabled |= mode; return; } if (0 == mon_mem_increments) mon_getmoremem(); /* * Select the MRU hash table size to limit the average count * per bucket at capacity (mru_maxdepth) to 8, if possible * given our hash is limited to 16 bits. */ min_hash_slots = (mru_maxdepth / 8) + 1; mon_hash_bits = 0; while (min_hash_slots >>= 1) mon_hash_bits++; mon_hash_bits = max(4, mon_hash_bits); mon_hash_bits = min(16, mon_hash_bits); octets = sizeof(*mon_hash) * MON_HASH_SIZE; mon_hash = erealloc_zero(mon_hash, octets, 0); mon_enabled = mode; }
u_int available_blocking_child_slot(void) { const size_t each = sizeof(blocking_children[0]); u_int slot; size_t prev_alloc; size_t new_alloc; size_t prev_octets; size_t octets; for (slot = 0; slot < blocking_children_alloc; slot++) { if (NULL == blocking_children[slot]) return slot; if (blocking_children[slot]->reusable) { blocking_children[slot]->reusable = FALSE; return slot; } } prev_alloc = blocking_children_alloc; prev_octets = prev_alloc * each; new_alloc = blocking_children_alloc + 4; octets = new_alloc * each; blocking_children = erealloc_zero(blocking_children, octets, prev_octets); blocking_children_alloc = new_alloc; return prev_alloc; }
u_int available_blocking_child_slot(void) { const size_t each = sizeof(blocking_children[0]); u_int slot; size_t prev_alloc; size_t new_alloc; size_t prev_octets; size_t octets; for (slot = 0; slot < blocking_children_alloc; slot++) { if (NULL == blocking_children[slot]) return slot; if (blocking_children[slot]->reusable) { blocking_children[slot]->reusable = FALSE; return slot; } } prev_alloc = blocking_children_alloc; prev_octets = prev_alloc * each; new_alloc = blocking_children_alloc + 4; octets = new_alloc * each; blocking_children = erealloc_zero(blocking_children, octets, prev_octets); blocking_children_alloc = new_alloc; /* assume we'll never have enough workers to overflow u_int */ return (u_int)prev_alloc; }
static void ensure_workresp_empty_slot( blocking_child *c ) { const size_t each = sizeof(blocking_children[0]->responses[0]); size_t new_alloc; size_t old_octets; size_t new_octets; void * nonvol_responses; if (c->responses != NULL && NULL == c->responses[c->next_response]) return; new_alloc = c->responses_alloc + RESPONSES_ALLOC_INC; old_octets = c->responses_alloc * each; new_octets = new_alloc * each; nonvol_responses = DEVOLATILE(void *, c->responses); c->responses = erealloc_zero(nonvol_responses, new_octets, old_octets); if (0 == c->next_response) c->next_response = c->responses_alloc; c->responses_alloc = new_alloc; }
static void ensure_workitems_empty_slot( blocking_child *c ) { const size_t each = sizeof(blocking_children[0]->workitems[0]); size_t new_alloc; size_t old_octets; size_t new_octets; void * nonvol_workitems; if (c->workitems != NULL && NULL == c->workitems[c->next_workitem]) return; new_alloc = c->workitems_alloc + WORKITEMS_ALLOC_INC; old_octets = c->workitems_alloc * each; new_octets = new_alloc * each; nonvol_workitems = DEVOLATILE(void *, c->workitems); c->workitems = erealloc_zero(nonvol_workitems, new_octets, old_octets); if (0 == c->next_workitem) c->next_workitem = c->workitems_alloc; c->workitems_alloc = new_alloc; }
/* * growpktdata - grow the packet data area */ static void growpktdata(void) { size_t priorsz; priorsz = (size_t)pktdatasize; pktdatasize += INCDATASIZE; pktdata = erealloc_zero(pktdata, (size_t)pktdatasize, priorsz); }
/* * common_serial_open ensures duplicate opens of the same port * work by duplicating the handle for the 2nd open, allowing * refclock_atom to share a GPS refclock's comm port. */ HANDLE common_serial_open( const char * dev, char ** pwindev ) { char * windev; HANDLE handle; size_t unit; size_t prev_c_hnds; size_t opens; const char * pch; /* * This is odd, but we'll take any unix device path * by looking for the initial '/' and strip off everything * before the final digits, then translate that to COM__: * maintaining backward compatibility with NTP practice of * mapping unit 0 to the nonfunctional COM0: * * To ease the job of taking the windows COMx: device names * out of reference clocks, we'll also work with those * equanimously. */ TRACE(1, ("common_serial_open given %s\n", dev)); pch = NULL; if ('/' == dev[0]) { pch = dev + strlen(dev) - 1; if (isdigit(pch[0])) { while (isdigit(pch[0])) { pch--; } pch++; } TRACE(1, ("common_serial_open skipped to ending digits leaving %s\n", pch)); } else if ('c' == tolower(dev[0]) && 'o' == tolower(dev[1]) && 'm' == tolower(dev[2])) { pch = dev + 3; TRACE(1, ("common_serial_open skipped COM leaving %s\n", pch)); } if (!pch || !isdigit(pch[0])) { TRACE(1, ("not a digit: %s\n", pch ? pch : "[NULL]")); return INVALID_HANDLE_VALUE; } if (1 != sscanf(pch, "%d", &unit) || unit > MAX_SERIAL || unit < 0) { TRACE(1, ("sscanf failure of %s\n", pch)); return INVALID_HANDLE_VALUE; } if (c_hnds < unit + 1) { prev_c_hnds = c_hnds; c_hnds = unit + 1; /* round up to closest multiple of 4 to avoid churn */ c_hnds = (c_hnds + 3) & ~3; hnds = erealloc_zero(hnds, c_hnds * sizeof(hnds[0]), prev_c_hnds * sizeof(hnds[0])); } if (NULL == hnds[unit].h) { INSIST(0 == hnds[unit].opens); LIB_GETBUF(windev); snprintf(windev, LIB_BUFLENGTH, "\\\\.\\COM%d", unit); TRACE(1, ("windows device %s\n", windev)); *pwindev = windev; hnds[unit].h = CreateFile( windev, GENERIC_READ | GENERIC_WRITE, 0, /* sharing prohibited */ NULL, /* default security */ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (INVALID_HANDLE_VALUE == hnds[unit].h) hnds[unit].h = NULL; } if (NULL != hnds[unit].h) { /* think handle = dup(hnds[unit].h); */ DuplicateHandle( GetCurrentProcess(), hnds[unit].h, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS ); hnds[unit].opens++; opens = hnds[unit].opens; hnds[unit].dupes = erealloc(hnds[unit].dupes, opens * sizeof(hnds[unit].dupes[0])); hnds[unit].dupes[opens - 1] = handle; return handle; } return INVALID_HANDLE_VALUE; }
/* * 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; sockaddr_u addr; size_t octets; 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. */ strlcpy(service, "ntp", sizeof(service)); ZERO(hints); hints.ai_family = ai_fam_templ; hints.ai_protocol = IPPROTO_UDP; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = Z_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) { 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. */ INSIST(ai != NULL); ZERO(addr); octets = min(sizeof(addr), ai->ai_addrlen); memcpy(&addr, ai->ai_addr, octets); if (ai->ai_canonname == NULL) strlcpy(temphost, stoa(&addr), sizeof(temphost)); else strlcpy(temphost, ai->ai_canonname, sizeof(temphost)); if (debug > 2) printf("Opening host %s\n", temphost); if (havehost == 1) { if (debug > 2) printf("Closing old host %s\n", currenthost); closesocket(sockfd); havehost = 0; } strlcpy(currenthost, temphost, sizeof(currenthost)); /* port maps to the same in both families */ s_port = NSRCPORT(&addr);; #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); } } #endif /* SYS_WINNT */ sockfd = socket(ai->ai_family, SOCK_DGRAM, 0); if (sockfd == INVALID_SOCKET) { error("socket"); exit(-1); } #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, ai->ai_addr, ai->ai_addrlen) == -1) { #endif /* SYS_VXWORKS */ error("connect"); exit(-1); } freeaddrinfo(ai); havehost = 1; req_pkt_size = REQ_LEN_NOMAC; impl_ver = IMPL_XNTPD; return 1; } /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */ /* * sendpkt - send a packet to the remote host */ static int sendpkt( void * xdata, size_t xdatalen ) { if (send(sockfd, xdata, xdatalen, 0) == -1) { warning("write to %s failed", currenthost); return -1; } return 0; } /* * growpktdata - grow the packet data area */ static void growpktdata(void) { size_t priorsz; priorsz = (size_t)pktdatasize; pktdatasize += INCDATASIZE; pktdata = erealloc_zero(pktdata, (size_t)pktdatasize, priorsz); }