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>