Annotation of embedaddon/ntp/lib/isc/win32/net.c, revision 1.1.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>