Annotation of embedaddon/ntp/lib/isc/win32/net.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
! 3: * Copyright (C) 1999-2003 Internet Software Consortium.
! 4: *
! 5: * Permission to use, copy, modify, and/or distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
! 15: * PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: /* $Id: net.c,v 1.18 2008/08/08 05:06:49 marka Exp $ */
! 19:
! 20: #include <config.h>
! 21:
! 22: #include <errno.h>
! 23: #include <unistd.h>
! 24:
! 25: #include <isc/log.h>
! 26: #include <isc/msgs.h>
! 27: #include <isc/net.h>
! 28: #include <isc/once.h>
! 29: #include <isc/strerror.h>
! 30: #include <isc/string.h>
! 31: #include <isc/util.h>
! 32:
! 33: /*%
! 34: * Definitions about UDP port range specification. This is a total mess of
! 35: * portability variants: some use sysctl (but the sysctl names vary), some use
! 36: * system-specific interfaces, some have the same interface for IPv4 and IPv6,
! 37: * some separate them, etc...
! 38: */
! 39:
! 40: /*%
! 41: * The last resort defaults: use all non well known port space
! 42: */
! 43: #ifndef ISC_NET_PORTRANGELOW
! 44: #define ISC_NET_PORTRANGELOW 1024
! 45: #endif /* ISC_NET_PORTRANGELOW */
! 46: #ifndef ISC_NET_PORTRANGEHIGH
! 47: #define ISC_NET_PORTRANGEHIGH 65535
! 48: #endif /* ISC_NET_PORTRANGEHIGH */
! 49:
! 50: #if defined(ISC_PLATFORM_NEEDIN6ADDRANY)
! 51: const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
! 52: #endif
! 53:
! 54: #if defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK)
! 55: const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT;
! 56: #endif
! 57:
! 58:
! 59: static isc_once_t once = ISC_ONCE_INIT;
! 60: static isc_once_t once_ipv6only = ISC_ONCE_INIT;
! 61: static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT;
! 62: static isc_result_t ipv4_result = ISC_R_NOTFOUND;
! 63: static isc_result_t ipv6_result = ISC_R_NOTFOUND;
! 64: static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
! 65: static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND;
! 66:
! 67: void InitSockets(void);
! 68:
! 69: static isc_result_t
! 70: try_proto(int domain) {
! 71: SOCKET s;
! 72: char strbuf[ISC_STRERRORSIZE];
! 73: int errval;
! 74:
! 75: s = socket(domain, SOCK_STREAM, IPPROTO_TCP);
! 76: if (s == INVALID_SOCKET) {
! 77: errval = WSAGetLastError();
! 78: switch (errval) {
! 79: case WSAEAFNOSUPPORT:
! 80: case WSAEPROTONOSUPPORT:
! 81: case WSAEINVAL:
! 82: return (ISC_R_NOTFOUND);
! 83: default:
! 84: isc__strerror(errval, strbuf, sizeof(strbuf));
! 85: UNEXPECTED_ERROR(__FILE__, __LINE__,
! 86: "socket() %s: %s",
! 87: isc_msgcat_get(isc_msgcat,
! 88: ISC_MSGSET_GENERAL,
! 89: ISC_MSG_FAILED,
! 90: "failed"),
! 91: strbuf);
! 92: return (ISC_R_UNEXPECTED);
! 93: }
! 94: }
! 95:
! 96: closesocket(s);
! 97:
! 98: return (ISC_R_SUCCESS);
! 99: }
! 100:
! 101: static void
! 102: initialize_action(void) {
! 103: InitSockets();
! 104: ipv4_result = try_proto(PF_INET);
! 105: #ifdef ISC_PLATFORM_HAVEIPV6
! 106: #ifdef WANT_IPV6
! 107: #ifdef ISC_PLATFORM_HAVEIN6PKTINFO
! 108: ipv6_result = try_proto(PF_INET6);
! 109: #endif
! 110: #endif
! 111: #endif
! 112: }
! 113:
! 114: static void
! 115: initialize(void) {
! 116: RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
! 117: }
! 118:
! 119: isc_result_t
! 120: isc_net_probeipv4(void) {
! 121: initialize();
! 122: return (ipv4_result);
! 123: }
! 124:
! 125: isc_result_t
! 126: isc_net_probeipv6(void) {
! 127: initialize();
! 128: return (ipv6_result);
! 129: }
! 130:
! 131: isc_result_t
! 132: isc_net_probeunix(void) {
! 133: return (ISC_R_NOTFOUND);
! 134: }
! 135:
! 136: #ifdef ISC_PLATFORM_HAVEIPV6
! 137: #ifdef WANT_IPV6
! 138: static void
! 139: try_ipv6only(void) {
! 140: #ifdef IPV6_V6ONLY
! 141: SOCKET s;
! 142: int on;
! 143: char strbuf[ISC_STRERRORSIZE];
! 144: #endif
! 145: isc_result_t result;
! 146:
! 147: result = isc_net_probeipv6();
! 148: if (result != ISC_R_SUCCESS) {
! 149: ipv6only_result = result;
! 150: return;
! 151: }
! 152:
! 153: #ifndef IPV6_V6ONLY
! 154: ipv6only_result = ISC_R_NOTFOUND;
! 155: return;
! 156: #else
! 157: /* check for TCP sockets */
! 158: s = socket(PF_INET6, SOCK_STREAM, 0);
! 159: if (s == INVALID_SOCKET) {
! 160: isc__strerror(errno, strbuf, sizeof(strbuf));
! 161: UNEXPECTED_ERROR(__FILE__, __LINE__,
! 162: "socket() %s: %s",
! 163: isc_msgcat_get(isc_msgcat,
! 164: ISC_MSGSET_GENERAL,
! 165: ISC_MSG_FAILED,
! 166: "failed"),
! 167: strbuf);
! 168: ipv6only_result = ISC_R_UNEXPECTED;
! 169: return;
! 170: }
! 171:
! 172: on = 1;
! 173: if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) {
! 174: ipv6only_result = ISC_R_NOTFOUND;
! 175: goto close;
! 176: }
! 177:
! 178: closesocket(s);
! 179:
! 180: /* check for UDP sockets */
! 181: s = socket(PF_INET6, SOCK_DGRAM, 0);
! 182: if (s == INVALID_SOCKET) {
! 183: isc__strerror(errno, strbuf, sizeof(strbuf));
! 184: UNEXPECTED_ERROR(__FILE__, __LINE__,
! 185: "socket() %s: %s",
! 186: isc_msgcat_get(isc_msgcat,
! 187: ISC_MSGSET_GENERAL,
! 188: ISC_MSG_FAILED,
! 189: "failed"),
! 190: strbuf);
! 191: ipv6only_result = ISC_R_UNEXPECTED;
! 192: return;
! 193: }
! 194:
! 195: on = 1;
! 196: if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) {
! 197: ipv6only_result = ISC_R_NOTFOUND;
! 198: goto close;
! 199: }
! 200:
! 201: ipv6only_result = ISC_R_SUCCESS;
! 202:
! 203: close:
! 204: closesocket(s);
! 205: return;
! 206: #endif /* IPV6_V6ONLY */
! 207: }
! 208:
! 209: static void
! 210: initialize_ipv6only(void) {
! 211: RUNTIME_CHECK(isc_once_do(&once_ipv6only,
! 212: try_ipv6only) == ISC_R_SUCCESS);
! 213: }
! 214:
! 215: static void
! 216: try_ipv6pktinfo(void) {
! 217: int s, on;
! 218: char strbuf[ISC_STRERRORSIZE];
! 219: isc_result_t result;
! 220: int optname;
! 221:
! 222: result = isc_net_probeipv6();
! 223: if (result != ISC_R_SUCCESS) {
! 224: ipv6pktinfo_result = result;
! 225: return;
! 226: }
! 227:
! 228: /* we only use this for UDP sockets */
! 229: s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
! 230: if (s == INVALID_SOCKET) {
! 231: isc__strerror(errno, strbuf, sizeof(strbuf));
! 232: UNEXPECTED_ERROR(__FILE__, __LINE__,
! 233: "socket() %s: %s",
! 234: isc_msgcat_get(isc_msgcat,
! 235: ISC_MSGSET_GENERAL,
! 236: ISC_MSG_FAILED,
! 237: "failed"),
! 238: strbuf);
! 239: ipv6pktinfo_result = ISC_R_UNEXPECTED;
! 240: return;
! 241: }
! 242:
! 243: #ifdef IPV6_RECVPKTINFO
! 244: optname = IPV6_RECVPKTINFO;
! 245: #else
! 246: optname = IPV6_PKTINFO;
! 247: #endif
! 248: on = 1;
! 249: if (setsockopt(s, IPPROTO_IPV6, optname, (const char *) &on,
! 250: sizeof(on)) < 0) {
! 251: ipv6pktinfo_result = ISC_R_NOTFOUND;
! 252: goto close;
! 253: }
! 254:
! 255: ipv6pktinfo_result = ISC_R_SUCCESS;
! 256:
! 257: close:
! 258: closesocket(s);
! 259: return;
! 260: }
! 261:
! 262: static void
! 263: initialize_ipv6pktinfo(void) {
! 264: RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
! 265: try_ipv6pktinfo) == ISC_R_SUCCESS);
! 266: }
! 267: #endif /* WANT_IPV6 */
! 268: #endif /* ISC_PLATFORM_HAVEIPV6 */
! 269:
! 270: isc_result_t
! 271: isc_net_probe_ipv6only(void) {
! 272: #ifdef ISC_PLATFORM_HAVEIPV6
! 273: #ifdef WANT_IPV6
! 274: initialize_ipv6only();
! 275: #else
! 276: ipv6only_result = ISC_R_NOTFOUND;
! 277: #endif
! 278: #endif
! 279: return (ipv6only_result);
! 280: }
! 281:
! 282: isc_result_t
! 283: isc_net_probe_ipv6pktinfo(void) {
! 284: #ifdef ISC_PLATFORM_HAVEIPV6
! 285: #ifdef WANT_IPV6
! 286: initialize_ipv6pktinfo();
! 287: #else
! 288: ipv6pktinfo_result = ISC_R_NOTFOUND;
! 289: #endif
! 290: #endif
! 291: return (ipv6pktinfo_result);
! 292: }
! 293:
! 294: isc_result_t
! 295: isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
! 296: int result = ISC_R_FAILURE;
! 297:
! 298: REQUIRE(low != NULL && high != NULL);
! 299:
! 300: UNUSED(af);
! 301:
! 302: if (result != ISC_R_SUCCESS) {
! 303: *low = ISC_NET_PORTRANGELOW;
! 304: *high = ISC_NET_PORTRANGEHIGH;
! 305: }
! 306:
! 307: return (ISC_R_SUCCESS); /* we currently never fail in this function */
! 308: }
! 309:
! 310: void
! 311: isc_net_disableipv4(void) {
! 312: initialize();
! 313: if (ipv4_result == ISC_R_SUCCESS)
! 314: ipv4_result = ISC_R_DISABLED;
! 315: }
! 316:
! 317: void
! 318: isc_net_disableipv6(void) {
! 319: initialize();
! 320: if (ipv6_result == ISC_R_SUCCESS)
! 321: ipv6_result = ISC_R_DISABLED;
! 322: }
! 323:
! 324: void
! 325: isc_net_enableipv4(void) {
! 326: initialize();
! 327: if (ipv4_result == ISC_R_DISABLED)
! 328: ipv4_result = ISC_R_SUCCESS;
! 329: }
! 330:
! 331: void
! 332: isc_net_enableipv6(void) {
! 333: initialize();
! 334: if (ipv6_result == ISC_R_DISABLED)
! 335: ipv6_result = ISC_R_SUCCESS;
! 336: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>