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