1 /* $NetBSD: networking.c,v 1.3 2010/08/28 20:54:24 kardel Exp $ */ 2 3 #include "networking.h" 4 5 char adr_buf[INET6_ADDRSTRLEN]; 6 7 8 /* resolve_hosts consumes an array of hostnames/addresses and its length, stores a pointer 9 * to the array with the resolved hosts in res and returns the size of the array res. 10 * pref_family enforces IPv4 or IPv6 depending on commandline options and system 11 * capability. If pref_family is NULL or PF_UNSPEC any compatible family will be accepted. 12 * Check here: Probably getaddrinfo() can do without ISC's IPv6 availability check? 13 */ 14 int 15 resolve_hosts ( 16 char **hosts, 17 int hostc, 18 struct addrinfo ***res, 19 int pref_family 20 ) 21 { 22 register unsigned int a; 23 unsigned int resc; 24 struct addrinfo **tres; 25 26 if (hostc < 1 || NULL == res) 27 return 0; 28 29 tres = emalloc(sizeof(struct addrinfo *) * hostc); 30 31 for (a = 0, resc = 0; a < hostc; a++) { 32 struct addrinfo hints; 33 int error; 34 35 tres[resc] = NULL; 36 37 #ifdef DEBUG 38 printf("sntp resolve_hosts: Starting host resolution for %s...\n", hosts[a]); 39 #endif 40 41 memset(&hints, 0, sizeof(hints)); 42 43 if (AF_UNSPEC == pref_family) 44 hints.ai_family = PF_UNSPEC; 45 else 46 hints.ai_family = pref_family; 47 48 hints.ai_socktype = SOCK_DGRAM; 49 50 error = getaddrinfo(hosts[a], "123", &hints, &tres[resc]); 51 52 if (error) { 53 size_t msg_length = strlen(hosts[a]) + 21; 54 char *logmsg = (char *) emalloc(sizeof(char) * msg_length); 55 56 snprintf(logmsg, msg_length, "Error looking up %s", hosts[a]); 57 #ifdef DEBUG 58 printf("%s\n", logmsg); 59 #endif 60 61 log_msg(logmsg, 1); 62 free(logmsg); 63 } else { 64 #ifdef DEBUG 65 struct addrinfo *dres; 66 67 for (dres = tres[resc]; dres; dres = dres->ai_next) { 68 getnameinfo(dres->ai_addr, dres->ai_addrlen, adr_buf, sizeof(adr_buf), NULL, 0, NI_NUMERICHOST); 69 STDLINE 70 printf("Resolv No.: %i Result of getaddrinfo for %s:\n", resc, hosts[a]); 71 printf("socktype: %i ", dres->ai_socktype); 72 printf("protocol: %i ", dres->ai_protocol); 73 printf("Prefered socktype: %i IP: %s\n", dres->ai_socktype, adr_buf); 74 STDLINE 75 } 76 #endif 77 resc++; 78 } 79 } 80 81 if (resc) 82 *res = realloc(tres, sizeof(struct addrinfo *) * resc); 83 else { 84 free(tres); 85 *res = NULL; 86 } 87 88 return resc; 89 } 90 91 /* Creates a socket and returns. */ 92 void 93 create_socket ( 94 SOCKET *rsock, 95 sockaddr_u *dest 96 ) 97 { 98 *rsock = socket(AF(dest), SOCK_DGRAM, 0); 99 100 if (-1 == *rsock && ENABLED_OPT(NORMALVERBOSE)) 101 printf("Failed to create UDP socket with family %d\n", AF(dest)); 102 } 103 104 /* Send a packet */ 105 void 106 sendpkt ( 107 SOCKET rsock, 108 sockaddr_u *dest, 109 struct pkt *pkt, 110 int len 111 ) 112 { 113 int cc; 114 115 #ifdef DEBUG 116 printf("sntp sendpkt: Packet data:\n"); 117 pkt_output(pkt, len, stdout); 118 #endif 119 120 if (ENABLED_OPT(NORMALVERBOSE)) { 121 getnameinfo(&dest->sa, SOCKLEN(dest), adr_buf, sizeof(adr_buf), NULL, 0, NI_NUMERICHOST); 122 123 printf("sntp sendpkt: Sending packet to %s... ", adr_buf); 124 } 125 126 cc = sendto(rsock, (void *)pkt, len, 0, &dest->sa, SOCKLEN(dest)); 127 128 if (cc == SOCKET_ERROR) { 129 #ifdef DEBUG 130 printf("\n sntp sendpkt: Socket error: %i. Couldn't send packet!\n", cc); 131 #endif 132 133 if (errno != EWOULDBLOCK && errno != ENOBUFS) { 134 135 } 136 } else if (ENABLED_OPT(NORMALVERBOSE)) 137 printf("Packet sent.\n"); 138 } 139 140 /* Receive raw data */ 141 int 142 recvdata ( 143 SOCKET rsock, 144 sockaddr_u *sender, 145 char *rdata, 146 int rdata_length 147 ) 148 { 149 GETSOCKNAME_SOCKLEN_TYPE slen; 150 int recvc; 151 152 #ifdef DEBUG 153 printf("sntp recvdata: Trying to receive data from...\n"); 154 #endif 155 slen = sizeof(sender->sas); 156 recvc = recvfrom(rsock, rdata, rdata_length, 0, 157 &sender->sa, &slen); 158 #ifdef DEBUG 159 if (recvc > 0) { 160 printf("Received %d bytes from %s:\n", recvc, stoa(sender)); 161 162 pkt_output((struct pkt *) rdata, recvc, stdout); 163 } 164 else { 165 int saved_errno = errno; 166 printf("recvfrom error %d (%s)\n", errno, strerror(errno)); 167 errno = saved_errno; 168 } 169 #endif 170 171 return recvc; 172 } 173 174 /* Receive data from broadcast. Couldn't finish that. Need to do some digging 175 * here, especially for protocol independence and IPv6 multicast */ 176 int 177 recv_bcst_data ( 178 SOCKET rsock, 179 char *rdata, 180 int rdata_len, 181 sockaddr_u *sas, 182 sockaddr_u *ras 183 ) 184 { 185 struct timeval timeout_tv; 186 fd_set bcst_fd; 187 char *buf; 188 int btrue = 1; 189 int recv_bytes = 0; 190 191 192 setsockopt(rsock, SOL_SOCKET, SO_REUSEADDR, &btrue, sizeof(btrue)); 193 194 if (IS_IPV4(sas)) { 195 struct ip_mreq mdevadr; 196 197 if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { 198 if (ENABLED_OPT(NORMALVERBOSE)) 199 printf("sntp recv_bcst_data: Couldn't bind() address.\n"); 200 } 201 202 203 if (setsockopt(rsock, IPPROTO_IP, IP_MULTICAST_LOOP, &btrue, sizeof(btrue)) < 0) { 204 /* some error message regarding setting up multicast loop */ 205 return BROADCAST_FAILED; 206 } 207 208 mdevadr.imr_multiaddr.s_addr = NSRCADR(sas); 209 mdevadr.imr_interface.s_addr = htonl(INADDR_ANY); 210 211 if (mdevadr.imr_multiaddr.s_addr == -1) { 212 if (ENABLED_OPT(NORMALVERBOSE)) { 213 printf("sntp recv_bcst_data: %s is not a broad-/multicast address, aborting...\n", 214 stoa(sas)); 215 } 216 217 return BROADCAST_FAILED; 218 } 219 220 if (setsockopt(rsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mdevadr, sizeof(mdevadr)) < 0) { 221 if (ENABLED_OPT(NORMALVERBOSE)) { 222 buf = ss_to_str(sas); 223 224 printf("sntp recv_bcst_data: Couldn't add IP membership for %s\n", buf); 225 226 free(buf); 227 228 return BROADCAST_FAILED; 229 } 230 } 231 } 232 #ifdef ISC_PLATFORM_HAVEIPV6 233 else if (IS_IPV6(sas)) { 234 #ifndef INCLUDE_IPV6_MULTICAST_SUPPORT 235 return BROADCAST_FAILED; 236 #else 237 struct ipv6_mreq mdevadr; 238 239 if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) { 240 if (ENABLED_OPT(NORMALVERBOSE)) 241 printf("sntp recv_bcst_data: Couldn't bind() address.\n"); 242 } 243 244 if (setsockopt(rsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &btrue, sizeof (btrue)) < 0) { 245 /* some error message regarding setting up multicast loop */ 246 return BROADCAST_FAILED; 247 } 248 249 memset(&mdevadr, 0, sizeof(mdevadr)); 250 mdevadr.ipv6mr_multiaddr = SOCK_ADDR6(sas); 251 252 if(!IN6_IS_ADDR_MULTICAST(&mdevadr.ipv6mr_multiaddr)) { 253 if(ENABLED_OPT(NORMALVERBOSE)) { 254 buf = ss_to_str(sas); 255 256 printf("sntp recv_bcst_data: %s is not a broad-/multicast address, aborting...\n", buf); 257 258 free(buf); 259 } 260 261 return BROADCAST_FAILED; 262 } 263 264 if (setsockopt(rsock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mdevadr, sizeof(mdevadr)) < 0) { 265 if(ENABLED_OPT(NORMALVERBOSE)) { 266 buf = ss_to_str(sas); 267 268 printf("sntp recv_bcst_data: Couldn't join group for %s\n", buf); 269 270 free(buf); 271 272 return BROADCAST_FAILED; 273 } 274 } 275 #endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ 276 } 277 #endif /* ISC_PLATFORM_HAVEIPV6 */ 278 279 FD_ZERO(&bcst_fd); 280 FD_SET(rsock, &bcst_fd); 281 282 if(ENABLED_OPT(TIMEOUT)) 283 timeout_tv.tv_sec = atol(OPT_ARG(TIMEOUT)); 284 else 285 timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */ 286 287 switch(select(rsock + 1, &bcst_fd, 0, 0, &timeout_tv)) { 288 FD_CLR(rsock, &bcst_fd); 289 290 case -1: 291 if(ENABLED_OPT(NORMALVERBOSE)) 292 printf("sntp recv_bcst_data: select() returned -1, an error occured, aborting.\n"); 293 294 return BROADCAST_FAILED; 295 break; 296 297 case 0: 298 if(ENABLED_OPT(NORMALVERBOSE)) 299 printf("sntp recv_bcst_data: select() reached timeout (%u sec), aborting.\n", 300 (unsigned)timeout_tv.tv_sec); 301 302 return BROADCAST_FAILED; 303 break; 304 305 default: 306 { 307 GETSOCKNAME_SOCKLEN_TYPE ss_len = sizeof(ras->sas); 308 309 recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len); 310 } 311 } 312 313 if (recv_bytes == -1) { 314 if(ENABLED_OPT(NORMALVERBOSE)) 315 printf("sntp recv_bcst_data: Failed to receive from broad-/multicast\n"); 316 317 return BROADCAST_FAILED; 318 } 319 320 if (IS_IPV4(sas)) 321 setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, sizeof(btrue)); 322 #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT 323 else if (IS_IPV6(sas)) 324 setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, sizeof(btrue)); 325 #endif 326 327 return recv_bytes; 328 } 329 330 int 331 recv_bcst_pkt ( 332 SOCKET rsock, 333 struct pkt *rpkt, 334 sockaddr_u *sas 335 ) 336 { 337 sockaddr_u sender; 338 register int a; 339 int is_authentic, has_mac = 0, orig_pkt_len; 340 341 char *rdata = emalloc(sizeof(char) * 256); 342 343 int pkt_len = recv_bcst_data(rsock, rdata, 256, sas, &sender); 344 345 346 if (pkt_len < 0) { 347 free(rdata); 348 349 return BROADCAST_FAILED; 350 } 351 352 /* No MAC, no authentication */ 353 if (LEN_PKT_NOMAC == pkt_len) 354 has_mac = 0; 355 356 /* If there's more than just the NTP packet it should be a MAC */ 357 else if(pkt_len > LEN_PKT_NOMAC) 358 has_mac = pkt_len - LEN_PKT_NOMAC; 359 else 360 if(ENABLED_OPT(NORMALVERBOSE)) { 361 printf("sntp recv_bcst_pkt: Funny packet length: %i. Discarding package.\n", pkt_len); 362 free(rdata); 363 364 return PACKET_UNUSEABLE; 365 } 366 367 /* Packet too big */ 368 if(pkt_len > LEN_PKT_NOMAC + MAX_MAC_LEN) { 369 if(ENABLED_OPT(NORMALVERBOSE)) 370 printf("sntp recv_bcst_pkt: Received packet is too big (%i bytes), trying again to get a useFable packet\n", 371 pkt_len); 372 free(rdata); 373 374 return PACKET_UNUSEABLE; 375 } 376 377 orig_pkt_len = pkt_len; 378 pkt_len = min(pkt_len, sizeof(struct pkt)); 379 380 /* Let's copy the received data to the packet structure */ 381 for (a = 0; a < pkt_len; a++) 382 if (a < orig_pkt_len) 383 ((char *)rpkt)[a] = rdata[a]; 384 else 385 ((char *)rpkt)[a] = 0; 386 387 free(rdata); 388 389 /* MAC could be useable for us */ 390 if (has_mac) { 391 /* Two more things that the MAC must conform to */ 392 if (has_mac > MAX_MAC_LEN || has_mac % 4 != 0) { 393 is_authentic = 0; /* Or should we discard this packet? */ 394 } 395 else { 396 if (MAX_MAC_LEN == has_mac) { 397 struct key *pkt_key = NULL; 398 399 /* Look for the key used by the server in the specified keyfile 400 * and if existent, fetch it or else leave the pointer untouched */ 401 get_key(rpkt->mac[0], &pkt_key); 402 403 /* Seems like we've got a key with matching keyid */ 404 if (pkt_key != NULL) { 405 /* Generate a md5sum of the packet with the key from our keyfile 406 * and compare those md5sums */ 407 if (!auth_md5((char *) rpkt, has_mac, pkt_key)) { 408 if (ENABLED_OPT(AUTHENTICATION)) { 409 /* We want a authenticated packet */ 410 if (ENABLED_OPT(NORMALVERBOSE)) { 411 char *hostname = ss_to_str(sas); 412 printf("sntp recv_bcst_pkt: Broadcast packet received from %s is not authentic. Will discard this packet.\n", 413 hostname); 414 415 free(hostname); 416 } 417 return SERVER_AUTH_FAIL; 418 } 419 else { 420 /* We don't know if the user wanted authentication so let's 421 * use it anyways */ 422 if (ENABLED_OPT(NORMALVERBOSE)) { 423 char *hostname = ss_to_str(sas); 424 printf("sntp recv_bcst_pkt: Broadcast packet received from %s is not authentic. Authentication not enforced.\n", 425 hostname); 426 427 free(hostname); 428 } 429 430 is_authentic = 0; 431 } 432 } 433 else { 434 /* Yay! Things worked out! */ 435 if (ENABLED_OPT(NORMALVERBOSE)) { 436 char *hostname = ss_to_str(sas); 437 printf("sntp recv_bcst_pkt: Broadcast packet received from %s successfully authenticated using key id %i.\n", 438 hostname, rpkt->mac[0]); 439 440 free(hostname); 441 } 442 443 is_authentic = 1; 444 } 445 } 446 } 447 } 448 } 449 450 /* Check for server's ntp version */ 451 if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || 452 PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { 453 if (ENABLED_OPT(NORMALVERBOSE)) 454 printf("sntp recv_bcst_pkt: Packet shows wrong version (%i)\n", 455 PKT_VERSION(rpkt->li_vn_mode)); 456 457 return SERVER_UNUSEABLE; 458 } 459 460 /* We want a server to sync with */ 461 if (PKT_MODE(rpkt->li_vn_mode) != MODE_BROADCAST 462 && PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) { 463 if (ENABLED_OPT(NORMALVERBOSE)) 464 printf("sntp recv_bcst_pkt: mode %d stratum %i\n", 465 PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); 466 467 return SERVER_UNUSEABLE; 468 } 469 470 if (STRATUM_PKT_UNSPEC == rpkt->stratum) { 471 char *ref_char; 472 473 if (ENABLED_OPT(NORMALVERBOSE)) 474 printf("sntp recv_bcst_pkt: Stratum unspecified, going to check for KOD (stratum: %i)\n", rpkt->stratum); 475 476 ref_char = (char *) &rpkt->refid; 477 478 /* If it's a KOD packet we'll just use the KOD information */ 479 if (ref_char[0] != 'X') { 480 if (strncmp(ref_char, "DENY", 4)) 481 return KOD_DEMOBILIZE; 482 483 if (strncmp(ref_char, "RSTR", 4)) 484 return KOD_DEMOBILIZE; 485 486 if (strncmp(ref_char, "RATE", 4)) 487 return KOD_RATE; 488 489 /* There are other interesting kiss codes which might be interesting for authentication */ 490 } 491 } 492 493 /* If the server is not synced it's not really useable for us */ 494 if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode)) { 495 if (ENABLED_OPT(NORMALVERBOSE)) 496 printf("recv_bcst_pkt: Server not in sync, skipping this server\n"); 497 498 return SERVER_UNUSEABLE; 499 } 500 501 return pkt_len; 502 } 503 504 505 506 /* Fetch data, check if it's data for us and whether it's useable or not. If not, return 507 * a failure code so we can delete this server from our list and continue with another one. 508 */ 509 int 510 recvpkt ( 511 SOCKET rsock, 512 struct pkt *rpkt, 513 struct pkt *spkt 514 ) 515 { 516 sockaddr_u sender; 517 char *rdata /* , done */; 518 519 register int a; 520 int has_mac, is_authentic, pkt_len, orig_pkt_len; 521 522 523 /* Much space, just to be sure */ 524 rdata = emalloc(sizeof(char) * 256); 525 526 pkt_len = recvdata(rsock, &sender, rdata, 256); 527 528 #if 0 /* done uninitialized */ 529 if (!done) { 530 /* Do something about it, first check for a maximum length of ntp packets, 531 * probably that's something we can avoid 532 */ 533 } 534 #endif 535 536 /* Some checks to see if that packet is intended for us */ 537 538 /* No MAC, no authentication */ 539 if (LEN_PKT_NOMAC == pkt_len) 540 has_mac = 0; 541 542 /* If there's more than just the NTP packet it should be a MAC */ 543 else if (pkt_len > LEN_PKT_NOMAC) 544 has_mac = pkt_len - LEN_PKT_NOMAC; 545 546 else { 547 if (ENABLED_OPT(NORMALVERBOSE)) 548 printf("sntp recvpkt: Funny packet length: %i. Discarding package.\n", pkt_len); 549 free(rdata); 550 551 return PACKET_UNUSEABLE; 552 } 553 554 /* Packet too big */ 555 if (pkt_len > LEN_PKT_MAC) { 556 if (ENABLED_OPT(NORMALVERBOSE)) 557 printf("sntp recvpkt: Received packet is too big (%i bytes), trying again to get a useable packet\n", 558 pkt_len); 559 free(rdata); 560 561 return PACKET_UNUSEABLE; 562 } 563 564 orig_pkt_len = pkt_len; 565 pkt_len = min(pkt_len, sizeof(struct pkt)); 566 567 for (a = 0; a < pkt_len; a++) 568 /* FIXME! */ 569 if (a < orig_pkt_len) 570 ((char *) rpkt)[a] = rdata[a]; 571 else 572 ((char *) rpkt)[a] = 0; 573 574 free(rdata); 575 rdata = NULL; 576 577 /* MAC could be useable for us */ 578 if (has_mac) { 579 /* Two more things that the MAC must conform to */ 580 if(has_mac > MAX_MAC_LEN || has_mac % 4 != 0) { 581 is_authentic = 0; /* Or should we discard this packet? */ 582 } 583 else { 584 if (MAX_MAC_LEN == has_mac) { 585 struct key *pkt_key = NULL; 586 587 /* 588 * Look for the key used by the server in the specified keyfile 589 * and if existent, fetch it or else leave the pointer untouched 590 */ 591 get_key(rpkt->mac[0], &pkt_key); 592 593 /* Seems like we've got a key with matching keyid */ 594 if (pkt_key != NULL) { 595 /* 596 * Generate a md5sum of the packet with the key from our keyfile 597 * and compare those md5sums 598 */ 599 if (!auth_md5((char *) rpkt, has_mac, pkt_key)) { 600 if (ENABLED_OPT(AUTHENTICATION)) { 601 /* We want a authenticated packet */ 602 if (ENABLED_OPT(NORMALVERBOSE)) { 603 char *hostname = ss_to_str(&sender); 604 printf("sntp recvpkt: Broadcast packet received from %s is not authentic. Will discard this packet.\n", 605 hostname); 606 607 free(hostname); 608 } 609 return SERVER_AUTH_FAIL; 610 } 611 else { 612 /* 613 * We don't know if the user wanted authentication so let's 614 * use it anyways 615 */ 616 if (ENABLED_OPT(NORMALVERBOSE)) { 617 char *hostname = ss_to_str(&sender); 618 printf("sntp recvpkt: Broadcast packet received from %s is not authentic. Authentication not enforced.\n", 619 hostname); 620 621 free(hostname); 622 } 623 624 is_authentic = 0; 625 } 626 } 627 else { 628 /* Yay! Things worked out! */ 629 if (ENABLED_OPT(NORMALVERBOSE)) { 630 char *hostname = ss_to_str(&sender); 631 printf("sntp recvpkt: Broadcast packet received from %s successfully authenticated using key id %i.\n", 632 hostname, rpkt->mac[0]); 633 634 free(hostname); 635 } 636 637 is_authentic = 1; 638 } 639 } 640 } 641 } 642 } 643 644 /* Check for server's ntp version */ 645 if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION || 646 PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) { 647 if (ENABLED_OPT(NORMALVERBOSE)) 648 printf("sntp recvpkt: Packet got wrong version (%i)\n", PKT_VERSION(rpkt->li_vn_mode)); 649 650 return SERVER_UNUSEABLE; 651 } 652 653 /* We want a server to sync with */ 654 if (PKT_MODE(rpkt->li_vn_mode) != MODE_SERVER && 655 PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) { 656 if (ENABLED_OPT(NORMALVERBOSE)) 657 printf("sntp recvpkt: mode %d stratum %i\n", 658 PKT_MODE(rpkt->li_vn_mode), rpkt->stratum); 659 660 return SERVER_UNUSEABLE; 661 } 662 663 /* Stratum is unspecified (0) check what's going on */ 664 if (STRATUM_PKT_UNSPEC == rpkt->stratum) { 665 char *ref_char; 666 667 if (ENABLED_OPT(NORMALVERBOSE)) 668 printf("sntp recvpkt: Stratum unspecified, going to check for KOD (stratum: %i)\n", rpkt->stratum); 669 670 671 ref_char = (char *) &rpkt->refid; 672 673 if (ENABLED_OPT(NORMALVERBOSE)) 674 printf("sntp recvpkt: Packet refid: %c%c%c%c\n", ref_char[0], ref_char[1], ref_char[2], ref_char[3]); 675 676 /* If it's a KOD packet we'll just use the KOD information */ 677 if (ref_char[0] != 'X') { 678 if (!strncmp(ref_char, "DENY", 4)) 679 return KOD_DEMOBILIZE; 680 681 if (!strncmp(ref_char, "RSTR", 4)) 682 return KOD_DEMOBILIZE; 683 684 if (!strncmp(ref_char, "RATE", 4)) 685 return KOD_RATE; 686 687 /* There are other interesting kiss codes which might be interesting for authentication */ 688 } 689 } 690 691 /* If the server is not synced it's not really useable for us */ 692 if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode)) { 693 if (ENABLED_OPT(NORMALVERBOSE)) 694 printf("sntp recvpkt: Server not in sync, skipping this server\n"); 695 696 return SERVER_UNUSEABLE; 697 } 698 699 /* 700 * Decode the org timestamp and make sure we're getting a response 701 * to our last request. 702 */ 703 704 #ifdef DEBUG 705 printf("rpkt->org:\n"); 706 l_fp_output(&rpkt->org, stdout); 707 printf("spkt->xmt:\n"); 708 l_fp_output(&spkt->xmt, stdout); 709 #endif 710 711 if (!L_ISEQU(&rpkt->org, &spkt->xmt)) { 712 if (ENABLED_OPT(NORMALVERBOSE)) 713 printf("sntp recvpkt: pkt.org and peer.xmt differ\n"); 714 715 return PACKET_UNUSEABLE; 716 } 717 718 return pkt_len; 719 } 720 721 /* 722 * is_reachable - check to see if we have a route to given destination 723 */ 724 int 725 is_reachable ( 726 struct addrinfo *dst 727 ) 728 { 729 SOCKET sockfd; 730 731 sockfd = socket(dst->ai_family, SOCK_DGRAM, 0); 732 733 if (-1 == sockfd) { 734 #ifdef DEBUG 735 printf("is_reachable: Couldn't create socket\n"); 736 #endif 737 return 0; 738 } 739 740 if (connect(sockfd, dst->ai_addr, SOCKLEN((sockaddr_u *)dst->ai_addr))) { 741 closesocket(sockfd); 742 return 0; 743 } 744 745 closesocket(sockfd); 746 return 1; 747 } 748