Annotation of embedaddon/ntp/sntp/networking.c, revision 1.1

1.1     ! misho       1: #include <config.h>
        !             2: #include "networking.h"
        !             3: 
        !             4: char adr_buf[INET6_ADDRSTRLEN];
        !             5: 
        !             6: 
        !             7: /* resolve_hosts consumes an array of hostnames/addresses and its length, stores a pointer
        !             8:  * to the array with the resolved hosts in res and returns the size of the array res.
        !             9:  * pref_family enforces IPv4 or IPv6 depending on commandline options and system 
        !            10:  * capability. If pref_family is NULL or PF_UNSPEC any compatible family will be accepted.
        !            11:  * Check here: Probably getaddrinfo() can do without ISC's IPv6 availability check? 
        !            12:  */
        !            13: int 
        !            14: resolve_hosts (
        !            15:                const char **hosts, 
        !            16:                int hostc, 
        !            17:                struct addrinfo ***res,
        !            18:                int pref_family
        !            19:                ) 
        !            20: {
        !            21:        register unsigned int a;
        !            22:        unsigned int resc;
        !            23:        struct addrinfo **tres;
        !            24: 
        !            25:        if (hostc < 1 || NULL == res)
        !            26:                return 0;
        !            27:        
        !            28:        tres = emalloc(sizeof(struct addrinfo *) * hostc);
        !            29:        for (a = 0, resc = 0; a < hostc; a++) {
        !            30:                struct addrinfo hints;
        !            31:                int error;
        !            32: 
        !            33:                tres[resc] = NULL;
        !            34: #ifdef DEBUG
        !            35:                printf("sntp resolve_hosts: Starting host resolution for %s...\n", hosts[a]); 
        !            36: #endif
        !            37:                memset(&hints, 0, sizeof(hints));
        !            38:                if (AF_UNSPEC == pref_family)
        !            39:                        hints.ai_family = PF_UNSPEC;
        !            40:                else 
        !            41:                        hints.ai_family = pref_family;
        !            42:                hints.ai_socktype = SOCK_DGRAM;
        !            43:                error = getaddrinfo(hosts[a], "123", &hints, &tres[resc]);
        !            44:                if (error) {
        !            45:                        msyslog(LOG_DEBUG, "Error looking up %s%s: %s",
        !            46:                                (AF_UNSPEC == hints.ai_family)
        !            47:                                    ? ""
        !            48:                                    : (AF_INET == hints.ai_family)
        !            49:                                          ? "(A) "
        !            50:                                          : "(AAAA) ",
        !            51:                                hosts[a], gai_strerror(error));
        !            52:                } else {
        !            53: #ifdef DEBUG
        !            54:                        for (dres = tres[resc]; dres; dres = dres->ai_next) {
        !            55:                                getnameinfo(dres->ai_addr, dres->ai_addrlen, adr_buf, sizeof(adr_buf), NULL, 0, NI_NUMERICHOST);
        !            56:                                STDLINE
        !            57:                                printf("Resolv No.: %i Result of getaddrinfo for %s:\n", resc, hosts[a]);
        !            58:                                printf("socktype: %i ", dres->ai_socktype); 
        !            59:                                printf("protocol: %i ", dres->ai_protocol);
        !            60:                                printf("Prefered socktype: %i IP: %s\n", dres->ai_socktype, adr_buf);
        !            61:                                STDLINE
        !            62:                        }
        !            63: #endif
        !            64:                        resc++;
        !            65:                }
        !            66:        }
        !            67: 
        !            68:        if (resc)
        !            69:                *res = realloc(tres, sizeof(struct addrinfo *) * resc);
        !            70:        else {
        !            71:                free(tres);
        !            72:                *res = NULL;
        !            73:        }
        !            74:        return resc;
        !            75: }
        !            76: 
        !            77: /* Creates a socket and returns. */
        !            78: void 
        !            79: create_socket (
        !            80:                SOCKET *rsock,
        !            81:                sockaddr_u *dest
        !            82:                )
        !            83: {
        !            84:        *rsock = socket(AF(dest), SOCK_DGRAM, 0);
        !            85: 
        !            86:        if (-1 == *rsock && ENABLED_OPT(NORMALVERBOSE))
        !            87:                printf("Failed to create UDP socket with family %d\n", AF(dest));
        !            88: }
        !            89: 
        !            90: /* Send a packet */
        !            91: void
        !            92: sendpkt (
        !            93:        SOCKET rsock,
        !            94:        sockaddr_u *dest,
        !            95:        struct pkt *pkt,
        !            96:        int len
        !            97:        )
        !            98: {
        !            99:        int cc;
        !           100: 
        !           101: #ifdef DEBUG
        !           102:        printf("sntp sendpkt: Packet data:\n");
        !           103:        pkt_output(pkt, len, stdout);
        !           104: #endif
        !           105: 
        !           106:        if (ENABLED_OPT(NORMALVERBOSE)) {
        !           107:                getnameinfo(&dest->sa, SOCKLEN(dest), adr_buf, sizeof(adr_buf), NULL, 0, NI_NUMERICHOST);
        !           108:                printf("sntp sendpkt: Sending packet to %s... ", adr_buf);
        !           109:        }
        !           110: 
        !           111:        cc = sendto(rsock, (void *)pkt, len, 0, &dest->sa, SOCKLEN(dest));
        !           112:        if (cc == SOCKET_ERROR) {
        !           113: #ifdef DEBUG
        !           114:                printf("\n sntp sendpkt: Socket error: %i. Couldn't send packet!\n", cc);
        !           115: #endif
        !           116:                if (errno != EWOULDBLOCK && errno != ENOBUFS) {
        !           117:                        /* oh well */
        !           118:                }
        !           119:        } else if (ENABLED_OPT(NORMALVERBOSE)) {
        !           120:                printf("Packet sent.\n");
        !           121:        }
        !           122: }
        !           123: 
        !           124: /* Receive raw data */
        !           125: int
        !           126: recvdata(
        !           127:        SOCKET rsock,
        !           128:        sockaddr_u *sender,
        !           129:        char *rdata,
        !           130:        int rdata_length
        !           131:        )
        !           132: {
        !           133:        GETSOCKNAME_SOCKLEN_TYPE slen;
        !           134:        int recvc;
        !           135: 
        !           136: #ifdef DEBUG
        !           137:        printf("sntp recvdata: Trying to receive data from...\n");
        !           138: #endif
        !           139:        slen = sizeof(*sender);
        !           140:        recvc = recvfrom(rsock, rdata, rdata_length, 0, 
        !           141:                         &sender->sa, &slen);
        !           142: #ifdef DEBUG
        !           143:        if (recvc > 0) {
        !           144:                printf("Received %d bytes from %s:\n", recvc, stoa(sender));
        !           145:                pkt_output((struct pkt *) rdata, recvc, stdout);
        !           146:        } else {
        !           147:                saved_errno = errno;
        !           148:                printf("recvfrom error %d (%s)\n", errno, strerror(errno));
        !           149:                errno = saved_errno;
        !           150:        }
        !           151: #endif
        !           152:        return recvc;
        !           153: }
        !           154: 
        !           155: /* Receive data from broadcast. Couldn't finish that. Need to do some digging
        !           156:  * here, especially for protocol independence and IPv6 multicast */
        !           157: int 
        !           158: recv_bcst_data (
        !           159:        SOCKET rsock,
        !           160:        char *rdata,
        !           161:        int rdata_len,
        !           162:        sockaddr_u *sas,
        !           163:        sockaddr_u *ras
        !           164:        )
        !           165: {
        !           166:        char *buf;
        !           167:        int btrue = 1;
        !           168:        int recv_bytes = 0;
        !           169:        int rdy_socks;
        !           170:        GETSOCKNAME_SOCKLEN_TYPE ss_len;
        !           171:        struct timeval timeout_tv;
        !           172:        fd_set bcst_fd;
        !           173: #ifdef MCAST
        !           174:        struct ip_mreq mdevadr;
        !           175:        TYPEOF_IP_MULTICAST_LOOP mtrue = 1;
        !           176: #endif
        !           177: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !           178:        struct ipv6_mreq mdevadr6;
        !           179: #endif
        !           180: 
        !           181:        setsockopt(rsock, SOL_SOCKET, SO_REUSEADDR, &btrue, sizeof(btrue));
        !           182:        if (IS_IPV4(sas)) {
        !           183:                if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) {
        !           184:                        if (ENABLED_OPT(NORMALVERBOSE))
        !           185:                                printf("sntp recv_bcst_data: Couldn't bind() address %s:%d.\n",
        !           186:                                       stoa(sas), SRCPORT(sas));
        !           187:                }
        !           188: 
        !           189: #ifdef MCAST
        !           190:                if (setsockopt(rsock, IPPROTO_IP, IP_MULTICAST_LOOP, &mtrue, sizeof(mtrue)) < 0) {
        !           191:                        /* some error message regarding setting up multicast loop */
        !           192:                        return BROADCAST_FAILED;
        !           193:                }
        !           194:                mdevadr.imr_multiaddr.s_addr = NSRCADR(sas); 
        !           195:                mdevadr.imr_interface.s_addr = htonl(INADDR_ANY);
        !           196:                if (mdevadr.imr_multiaddr.s_addr == -1) {
        !           197:                        if (ENABLED_OPT(NORMALVERBOSE)) {
        !           198:                                printf("sntp recv_bcst_data: %s:%d is not a broad-/multicast address, aborting...\n",
        !           199:                                       stoa(sas), SRCPORT(sas));
        !           200:                        }
        !           201:                        return BROADCAST_FAILED;
        !           202:                }
        !           203:                if (setsockopt(rsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mdevadr, sizeof(mdevadr)) < 0) {
        !           204:                        if (ENABLED_OPT(NORMALVERBOSE)) {
        !           205:                                buf = ss_to_str(sas);
        !           206:                                printf("sntp recv_bcst_data: Couldn't add IP membership for %s\n", buf);
        !           207:                                free(buf);
        !           208:                        }
        !           209:                }
        !           210: #endif /* MCAST */
        !           211:        }
        !           212: #ifdef ISC_PLATFORM_HAVEIPV6
        !           213:        else if (IS_IPV6(sas)) {
        !           214:                if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) {
        !           215:                        if (ENABLED_OPT(NORMALVERBOSE))
        !           216:                                printf("sntp recv_bcst_data: Couldn't bind() address.\n");
        !           217:                }
        !           218: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !           219:                if (setsockopt(rsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &btrue, sizeof (btrue)) < 0) {
        !           220:                        /* some error message regarding setting up multicast loop */
        !           221:                        return BROADCAST_FAILED;
        !           222:                }
        !           223:                memset(&mdevadr6, 0, sizeof(mdevadr6));
        !           224:                mdevadr6.ipv6mr_multiaddr = SOCK_ADDR6(sas);
        !           225:                if (!IN6_IS_ADDR_MULTICAST(&mdevadr6.ipv6mr_multiaddr)) {
        !           226:                        if (ENABLED_OPT(NORMALVERBOSE)) {
        !           227:                                buf = ss_to_str(sas); 
        !           228:                                printf("sntp recv_bcst_data: %s is not a broad-/multicast address, aborting...\n", buf);
        !           229:                                free(buf);
        !           230:                        }
        !           231:                        return BROADCAST_FAILED;
        !           232:                }
        !           233:                if (setsockopt(rsock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
        !           234:                               &mdevadr6, sizeof(mdevadr6)) < 0) {
        !           235:                        if (ENABLED_OPT(NORMALVERBOSE)) {
        !           236:                                buf = ss_to_str(sas); 
        !           237:                                printf("sntp recv_bcst_data: Couldn't join group for %s\n", buf);
        !           238:                                free(buf);
        !           239:                        }
        !           240:                }
        !           241: #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
        !           242:        }
        !           243: #endif /* ISC_PLATFORM_HAVEIPV6 */
        !           244:        FD_ZERO(&bcst_fd);
        !           245:        FD_SET(rsock, &bcst_fd);
        !           246:        if (ENABLED_OPT(TIMEOUT)) 
        !           247:                timeout_tv.tv_sec = (int) OPT_ARG(TIMEOUT);
        !           248:        else 
        !           249:                timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */
        !           250:        timeout_tv.tv_usec = 0;
        !           251:        rdy_socks = select(rsock + 1, &bcst_fd, 0, 0, &timeout_tv);
        !           252:        switch (rdy_socks) {
        !           253:        case -1: 
        !           254:                if (ENABLED_OPT(NORMALVERBOSE)) 
        !           255:                        perror("sntp recv_bcst_data: select()");
        !           256:                return BROADCAST_FAILED;
        !           257:                break;
        !           258:        case 0:
        !           259:                if (ENABLED_OPT(NORMALVERBOSE))
        !           260:                        printf("sntp recv_bcst_data: select() reached timeout (%u sec), aborting.\n", 
        !           261:                               (unsigned)timeout_tv.tv_sec);
        !           262:                return BROADCAST_FAILED;
        !           263:                break;
        !           264:        default:
        !           265:                ss_len = sizeof(*ras);
        !           266:                recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len);
        !           267:                break;
        !           268:        }
        !           269:        if (recv_bytes == -1) {
        !           270:                if (ENABLED_OPT(NORMALVERBOSE))
        !           271:                        perror("sntp recv_bcst_data: recvfrom:");
        !           272:                recv_bytes = BROADCAST_FAILED;
        !           273:        }
        !           274: #ifdef MCAST
        !           275:        if (IS_IPV4(sas)) 
        !           276:                setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, sizeof(btrue));
        !           277: #endif
        !           278: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
        !           279:        if (IS_IPV6(sas))
        !           280:                setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, sizeof(btrue));
        !           281: #endif
        !           282:        return recv_bytes;
        !           283: }
        !           284: 
        !           285: int
        !           286: process_pkt (
        !           287:        struct pkt *rpkt,
        !           288:        sockaddr_u *sas,
        !           289:        int pkt_len,
        !           290:        int mode,
        !           291:        struct pkt *spkt,
        !           292:        char * func_name
        !           293:        )
        !           294: {
        !           295:        unsigned int key_id = 0;
        !           296:        struct key *pkt_key = NULL;
        !           297:        int is_authentic = 0;
        !           298:        unsigned int exten_words, exten_words_used = 0;
        !           299:        int mac_size;
        !           300:        /*
        !           301:         * Parse the extension field if present. We figure out whether
        !           302:         * an extension field is present by measuring the MAC size. If
        !           303:         * the number of words following the packet header is 0, no MAC
        !           304:         * is present and the packet is not authenticated. If 1, the
        !           305:         * packet is a crypto-NAK; if 3, the packet is authenticated
        !           306:         * with DES; if 5, the packet is authenticated with MD5; if 6,
        !           307:         * the packet is authenticated with SHA. If 2 or 4, the packet
        !           308:         * is a runt and discarded forthwith. If greater than 6, an
        !           309:         * extension field is present, so we subtract the length of the
        !           310:         * field and go around again.
        !           311:         */
        !           312:        if (pkt_len < LEN_PKT_NOMAC || (pkt_len & 3) != 0) {
        !           313: unusable:
        !           314:                if (ENABLED_OPT(NORMALVERBOSE))
        !           315:                        printf("sntp %s: Funny packet length: %i. Discarding package.\n", func_name, pkt_len);
        !           316:                return PACKET_UNUSEABLE;
        !           317:        }
        !           318:        /* skip past the extensions, if any */
        !           319:        exten_words = ((unsigned)pkt_len - LEN_PKT_NOMAC) >> 2;
        !           320:        while (exten_words > 6) {
        !           321:                unsigned int exten_len;
        !           322:                exten_len = ntohl(rpkt->exten[exten_words_used]) & 0xffff;
        !           323:                exten_len = (exten_len + 7) >> 2; /* convert to words, add 1 */
        !           324:                if (exten_len > exten_words || exten_len < 5)
        !           325:                        goto unusable;
        !           326:                exten_words -= exten_len;
        !           327:                exten_words_used += exten_len;
        !           328:        }
        !           329: 
        !           330:        switch (exten_words) {
        !           331:        case 1:
        !           332:                key_id = ntohl(rpkt->exten[exten_words_used]);
        !           333:                printf("Crypto NAK = 0x%08x\n", key_id);
        !           334:                break;
        !           335:        case 5:
        !           336:        case 6:
        !           337:                /* Look for the key used by the server in the specified keyfile
        !           338:                 * and if existent, fetch it or else leave the pointer untouched */
        !           339:                key_id = ntohl(rpkt->exten[exten_words_used]);
        !           340:                get_key(key_id, &pkt_key);
        !           341:                if (!pkt_key) {
        !           342:                        printf("unrecognized key ID = 0x%08x\n", key_id);
        !           343:                        break;
        !           344:                }
        !           345:                /* Seems like we've got a key with matching keyid */
        !           346:                /* Generate a md5sum of the packet with the key from our keyfile
        !           347:                 * and compare those md5sums */
        !           348:                mac_size = exten_words << 2;
        !           349:                if (!auth_md5((char *)rpkt, pkt_len - mac_size, mac_size - 4, pkt_key)) {
        !           350:                        break;
        !           351:                }
        !           352:                /* Yay! Things worked out! */
        !           353:                if (ENABLED_OPT(NORMALVERBOSE)) {
        !           354:                        char *hostname = ss_to_str(sas);
        !           355:                        printf("sntp %s: packet received from %s successfully authenticated using key id %i.\n",
        !           356:                                func_name, hostname, key_id);
        !           357:                        free(hostname);
        !           358:                }
        !           359:                is_authentic = 1;
        !           360:                break;
        !           361:        case 0:
        !           362:                break;
        !           363:        default:
        !           364:                goto unusable;
        !           365:                break;
        !           366:        }
        !           367:        if (!is_authentic) {
        !           368:                if (ENABLED_OPT(AUTHENTICATION)) {
        !           369:                        /* We want a authenticated packet */
        !           370:                        if (ENABLED_OPT(NORMALVERBOSE)) {
        !           371:                                char *hostname = ss_to_str(sas);
        !           372:                                printf("sntp %s: packet received from %s is not authentic. Will discard it.\n",
        !           373:                                        func_name, hostname);
        !           374:                                free(hostname);
        !           375:                        }
        !           376:                        return SERVER_AUTH_FAIL;
        !           377:                }
        !           378:                /* We don't know if the user wanted authentication so let's 
        !           379:                 * use it anyways */
        !           380:                if (ENABLED_OPT(NORMALVERBOSE)) {
        !           381:                        char *hostname = ss_to_str(sas);
        !           382:                        printf("sntp %s: packet received from %s is not authentic. Authentication not enforced.\n",
        !           383:                                func_name, hostname);
        !           384:                        free(hostname);
        !           385:                }
        !           386:        }
        !           387:        /* Check for server's ntp version */
        !           388:        if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
        !           389:                PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
        !           390:                if (ENABLED_OPT(NORMALVERBOSE))
        !           391:                        printf("sntp %s: Packet shows wrong version (%i)\n",
        !           392:                                func_name, PKT_VERSION(rpkt->li_vn_mode));
        !           393:                return SERVER_UNUSEABLE;
        !           394:        } 
        !           395:        /* We want a server to sync with */
        !           396:        if (PKT_MODE(rpkt->li_vn_mode) != mode &&
        !           397:            PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) {
        !           398:                if (ENABLED_OPT(NORMALVERBOSE))
        !           399:                        printf("sntp %s: mode %d stratum %i\n", func_name, 
        !           400:                               PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
        !           401:                return SERVER_UNUSEABLE;
        !           402:        }
        !           403:        /* Stratum is unspecified (0) check what's going on */
        !           404:        if (STRATUM_PKT_UNSPEC == rpkt->stratum) {
        !           405:                char *ref_char;
        !           406:                if (ENABLED_OPT(NORMALVERBOSE))
        !           407:                        printf("sntp %s: Stratum unspecified, going to check for KOD (stratum: %i)\n", 
        !           408:                                func_name, rpkt->stratum);
        !           409:                ref_char = (char *) &rpkt->refid;
        !           410:                if (ENABLED_OPT(NORMALVERBOSE))
        !           411:                        printf("sntp %s: Packet refid: %c%c%c%c\n", func_name,
        !           412:                               ref_char[0], ref_char[1], ref_char[2], ref_char[3]);
        !           413:                /* If it's a KOD packet we'll just use the KOD information */
        !           414:                if (ref_char[0] != 'X') {
        !           415:                        if (strncmp(ref_char, "DENY", 4) == 0)
        !           416:                                return KOD_DEMOBILIZE;
        !           417:                        if (strncmp(ref_char, "RSTR", 4) == 0)
        !           418:                                return KOD_DEMOBILIZE;
        !           419:                        if (strncmp(ref_char, "RATE", 4) == 0)
        !           420:                                return KOD_RATE;
        !           421:                        /* There are other interesting kiss codes which might be interesting for authentication */
        !           422:                }
        !           423:        }
        !           424:        /* If the server is not synced it's not really useable for us */
        !           425:        if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode)) {
        !           426:                if (ENABLED_OPT(NORMALVERBOSE)) 
        !           427:                        printf("sntp %s: Server not in sync, skipping this server\n", func_name);
        !           428:                return SERVER_UNUSEABLE;
        !           429:        }
        !           430: 
        !           431:        /*
        !           432:         * Decode the org timestamp and make sure we're getting a response
        !           433:         * to our last request, but only if we're not in broadcast mode.
        !           434:         */
        !           435: #ifdef DEBUG
        !           436:        printf("rpkt->org:\n");
        !           437:        l_fp_output(&rpkt->org, stdout);
        !           438:        printf("spkt->xmt:\n");
        !           439:        l_fp_output(&spkt->xmt, stdout);
        !           440: #endif
        !           441:        if (mode != MODE_BROADCAST && !L_ISEQU(&rpkt->org, &spkt->xmt)) {
        !           442:                if (ENABLED_OPT(NORMALVERBOSE))
        !           443:                        printf("sntp process_pkt: pkt.org and peer.xmt differ\n");
        !           444:                return PACKET_UNUSEABLE;
        !           445:        }
        !           446: 
        !           447:        return pkt_len;
        !           448: }
        !           449: 
        !           450: int 
        !           451: recv_bcst_pkt (
        !           452:        SOCKET rsock,
        !           453:        struct pkt *rpkt,
        !           454:        unsigned int rsize,
        !           455:        sockaddr_u *sas
        !           456:        )
        !           457: {
        !           458:        sockaddr_u sender;
        !           459:        int pkt_len = recv_bcst_data(rsock, (char *)rpkt, rsize, sas, &sender);
        !           460:        if (pkt_len < 0) {
        !           461:                return BROADCAST_FAILED;
        !           462:        }
        !           463:        pkt_len = process_pkt(rpkt, sas, pkt_len, MODE_BROADCAST, NULL, "recv_bcst_pkt");
        !           464:        return pkt_len;
        !           465: }
        !           466: 
        !           467: /* Fetch data, check if it's data for us and whether it's useable or not. If not, return
        !           468:  * a failure code so we can delete this server from our list and continue with another one.
        !           469:  */
        !           470: int
        !           471: recvpkt (
        !           472:        SOCKET rsock,
        !           473:        struct pkt *rpkt,    /* received packet (response) */
        !           474:        unsigned int rsize,  /* size of rpkt buffer */
        !           475:        struct pkt *spkt     /* sent     packet (request) */
        !           476:        )
        !           477: {
        !           478:        int rdy_socks;
        !           479:        int pkt_len;
        !           480:        sockaddr_u sender;
        !           481:        struct timeval timeout_tv;
        !           482:        fd_set recv_fd;
        !           483: 
        !           484:        FD_ZERO(&recv_fd);
        !           485:        FD_SET(rsock, &recv_fd);
        !           486:        if (ENABLED_OPT(TIMEOUT)) 
        !           487:                timeout_tv.tv_sec = (int) OPT_ARG(TIMEOUT);
        !           488:        else 
        !           489:                timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */
        !           490:        timeout_tv.tv_usec = 0;
        !           491:        rdy_socks = select(rsock + 1, &recv_fd, 0, 0, &timeout_tv);
        !           492:        switch (rdy_socks) {
        !           493:        case -1: 
        !           494:                if (ENABLED_OPT(NORMALVERBOSE)) 
        !           495:                        perror("sntp recvpkt: select()");
        !           496:                return PACKET_UNUSEABLE;
        !           497:                break;
        !           498:        case 0:
        !           499:                if (ENABLED_OPT(NORMALVERBOSE))
        !           500:                        printf("sntp recvpkt: select() reached timeout (%u sec), aborting.\n", 
        !           501:                               (unsigned)timeout_tv.tv_sec);
        !           502:                return PACKET_UNUSEABLE;
        !           503:                break;
        !           504:        default:
        !           505:                break;
        !           506:        }
        !           507:        pkt_len = recvdata(rsock, &sender, (char *)rpkt, rsize);
        !           508:        if (pkt_len > 0)
        !           509:                pkt_len = process_pkt(rpkt, &sender, pkt_len, MODE_SERVER, spkt, "recvpkt");
        !           510: 
        !           511:        return pkt_len;
        !           512: }
        !           513: 
        !           514: /*
        !           515:  * is_reachable - check to see if we have a route to given destination
        !           516:  */
        !           517: int
        !           518: is_reachable (
        !           519:        struct addrinfo *dst
        !           520:        )
        !           521: {
        !           522:        SOCKET sockfd = socket(dst->ai_family, SOCK_DGRAM, 0);
        !           523: 
        !           524:        if (-1 == sockfd) {
        !           525: #ifdef DEBUG
        !           526:                printf("is_reachable: Couldn't create socket\n");
        !           527: #endif
        !           528:                return 0;
        !           529:        }
        !           530:        if (connect(sockfd, dst->ai_addr, SOCKLEN((sockaddr_u *)dst->ai_addr))) {
        !           531:                closesocket(sockfd);
        !           532:                return 0;
        !           533:        }
        !           534:        closesocket(sockfd);
        !           535:        return 1;
        !           536: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>