Annotation of embedaddon/ntp/sntp/networking.c, revision 1.1.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>