int isc_win32os_versioncheck(unsigned int major, unsigned int minor, unsigned int spmajor, unsigned int spminor) { initialize_action(); if (major < isc_win32os_majorversion()) return (1); if (major > isc_win32os_majorversion()) return (-1); if (minor < isc_win32os_minorversion()) return (1); if (minor > isc_win32os_minorversion()) return (-1); if (spmajor < isc_win32os_servicepackmajor()) return (1); if (spmajor > isc_win32os_servicepackmajor()) return (-1); if (spminor < isc_win32os_servicepackminor()) return (1); if (spminor > isc_win32os_servicepackminor()) return (-1); /* Exact */ return (0); }
/* * Due to Knowledge base article Q263823 we need to make sure that * Windows 2000 systems have Service Pack 2 or later installed and * warn when it isn't. */ static void version_check(const char *progname) { if(isc_win32os_majorversion() < 5) return; /* No problem with Version 4.0 */ if(isc_win32os_versioncheck(5, 0, 2, 0) < 0) if (ntservice_isservice()) NTReportError(progname, version_error); else fprintf(stderr, "%s\n", version_error); }
isc_result_t isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { char strbuf[ISC_STRERRORSIZE]; isc_interfaceiter_t *iter; isc_result_t result; unsigned int major; unsigned int minor; unsigned int spmajor; ULONG err; int tries; int error; unsigned long bytesReturned = 0; REQUIRE(mctx != NULL); REQUIRE(iterp != NULL); REQUIRE(*iterp == NULL); iter = isc_mem_get(mctx, sizeof(*iter)); if (iter == NULL) return (ISC_R_NOMEMORY); InitSockets(); iter->mctx = mctx; iter->ipaa = NULL; iter->buf4 = NULL; iter->buf6 = NULL; iter->pos4 = NULL; iter->ipaaCur = NULL; iter->ipuaCur = NULL; iter->ipaasize = 0; iter->pos6 = 0; iter->buf6size = 0; iter->buf4size = 0; iter->result = ISC_R_FAILURE; iter->numIF = 0; iter->v4IF = 0; /* * Use GetAdaptersAddresses in preference to ioctls when running * on Windows XP SP1 or later. Earlier GetAdaptersAddresses do * not appear to provide enough information to associate unicast * addresses with their prefixes. */ if (!use_GAA_determined) { major = isc_win32os_majorversion(); minor = isc_win32os_minorversion(); spmajor = isc_win32os_servicepackmajor(); if (major > 5 || (5 == major && (minor > 1 || (1 == minor && spmajor >= 1)))) { if (NULL == hmod_iphlpapi) hmod_iphlpapi = LoadLibrary("iphlpapi"); if (NULL != hmod_iphlpapi) pGAA = (PGETADAPTERSADDRESSES) GetProcAddress( hmod_iphlpapi, "GetAdaptersAddresses"); if (NULL != pGAA) use_GAA = ISC_TRUE; } use_GAA_determined = ISC_TRUE; } if (!use_GAA) goto use_ioctls; iter->ipaasize = 16 * 1024; for (tries = 0; tries < 5; tries++) { iter->ipaa = isc_mem_reallocate(mctx, iter->ipaa, iter->ipaasize); if (NULL == iter->ipaa) { result = ISC_R_NOMEMORY; goto put_iter; } err = (*pGAA)( AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST, NULL, iter->ipaa, &iter->ipaasize); if (NO_ERROR == err || ERROR_BUFFER_OVERFLOW != err) break; } if (NO_ERROR != err) { isc__strerror(err, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "GetAdaptersAddresses: %s", strbuf); result = ISC_R_UNEXPECTED; goto gaa_failure; } iter->ipaaCur = iter->ipaa; goto success; use_ioctls: /* * Create an unbound datagram socket to do the * SIO_GET_INTERFACE_LIST WSAIoctl on. */ if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { error = WSAGetLastError(); if (error == WSAEAFNOSUPPORT) goto inet6_only; isc__strerror(error, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "making interface scan socket: %s", strbuf); result = ISC_R_UNEXPECTED; goto put_iter; } /* * Get the interface configuration, allocating more memory if * necessary. */ iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO); for (;;) { iter->buf4 = isc_mem_get(mctx, iter->buf4size); if (iter->buf4 == NULL) { result = ISC_R_NOMEMORY; goto alloc_failure; } if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST, 0, 0, iter->buf4, iter->buf4size, &bytesReturned, 0, 0) == SOCKET_ERROR) { error = WSAGetLastError(); if (error != WSAEFAULT && error != WSAENOBUFS) { errno = error; isc__strerror(error, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "get interface configuration: %s", strbuf); result = ISC_R_UNEXPECTED; goto ioctl_failure; } /* * EINVAL. Retry with a bigger buffer. */ } else { /* * The WSAIoctl succeeded. * If the number of the returned bytes is the same * as the buffer size, we will grow it just in * case and retry. */ if (bytesReturned > 0 && (bytesReturned < iter->buf4size)) break; } if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) { UNEXPECTED_ERROR(__FILE__, __LINE__, "get interface configuration: " "maximum buffer size exceeded"); result = ISC_R_UNEXPECTED; goto ioctl_failure; } isc_mem_put(mctx, iter->buf4, iter->buf4size); iter->buf4size += IFCONF_SIZE_INCREMENT * sizeof(INTERFACE_INFO); } /* * A newly created iterator has an undefined position * until isc_interfaceiter_first() is called. */ iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO); /* We don't need the socket any more, so close it */ closesocket(iter->socket); inet6_only: /* * Create an unbound datagram socket to do the * SIO_ADDRESS_LIST_QUERY WSAIoctl on. */ if ((iter->socket = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { error = WSAGetLastError(); if (error == WSAEAFNOSUPPORT) goto success; isc__strerror(error, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "making interface scan socket: %s", strbuf); result = ISC_R_UNEXPECTED; goto put_iter; } /* * Get the interface configuration, allocating more memory if * necessary. */ iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) + IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS); for (;;) { iter->buf6 = isc_mem_get(mctx, iter->buf6size); if (iter->buf6 == NULL) { result = ISC_R_NOMEMORY; goto ioctl_failure; } if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY, 0, 0, iter->buf6, iter->buf6size, &bytesReturned, 0, 0) == SOCKET_ERROR) { error = WSAGetLastError(); if (error != WSAEFAULT && error != WSAENOBUFS) { errno = error; isc__strerror(error, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "sio address list query: %s", strbuf); result = ISC_R_UNEXPECTED; goto ioctl6_failure; } /* * EINVAL. Retry with a bigger buffer. */ } else break; if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) { UNEXPECTED_ERROR(__FILE__, __LINE__, "get interface configuration: " "maximum buffer size exceeded"); result = ISC_R_UNEXPECTED; goto ioctl6_failure; } isc_mem_put(mctx, iter->buf6, iter->buf6size); iter->buf6size += IFCONF_SIZE_INCREMENT * sizeof(SOCKET_ADDRESS); } /* * initialize loop__1 to [::1] and loopfe80__1 to [fe80::1]. * used by internal_current6(). */ memset(&iter->loop__1, 0, sizeof(iter->loop__1)); memset(&iter->loopfe80__1, 0, sizeof(iter->loopfe80__1)); iter->loop__1.s6_addr[15] = 1; iter->loopfe80__1.s6_addr[15] = 1; iter->loopfe80__1.s6_addr[0] = 0xfe; iter->loopfe80__1.s6_addr[1] = 0x80; closesocket(iter->socket); success: iter->magic = IFITER_MAGIC; *iterp = iter; return (ISC_R_SUCCESS); gaa_failure: isc_mem_put(mctx, iter->ipaa, iter->ipaasize); goto put_iter; ioctl6_failure: isc_mem_put(mctx, iter->buf6, iter->buf6size); ioctl_failure: if (iter->buf4 != NULL) isc_mem_put(mctx, iter->buf4, iter->buf4size); alloc_failure: if (iter->socket >= 0) (void) closesocket(iter->socket); put_iter: isc_mem_put(mctx, iter, sizeof(*iter)); return (result); }