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