001 package org.apache.commons.net.ntp; 002 /* 003 * Copyright 2001-2005 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 import java.net.DatagramPacket; 018 019 /*** 020 * Implementation of NtpV3Packet with methods converting Java objects to/from 021 * the Network Time Protocol (NTP) data message header format described in RFC-1305. 022 * 023 * @author Naz Irizarry, MITRE Corp 024 * @author Jason Mathews, MITRE Corp 025 * 026 * @version $Revision: 165675 $ $Date: 2005-05-02 21:09:55 +0100 (Mon, 02 May 2005) $ 027 */ 028 public class NtpV3Impl implements NtpV3Packet 029 { 030 031 private static final int MODE_INDEX = 0; 032 private static final int MODE_SHIFT = 0; 033 034 private static final int VERSION_INDEX = 0; 035 private static final int VERSION_SHIFT = 3; 036 037 private static final int LI_INDEX = 0; 038 private static final int LI_SHIFT = 6; 039 040 private static final int STRATUM_INDEX = 1; 041 private static final int POLL_INDEX = 2; 042 private static final int PRECISION_INDEX = 3; 043 044 private static final int ROOT_DELAY_INDEX = 4; 045 private static final int ROOT_DISPERSION_INDEX = 8; 046 private static final int REFERENCE_ID_INDEX = 12; 047 048 private static final int REFERENCE_TIMESTAMP_INDEX = 16; 049 private static final int ORIGINATE_TIMESTAMP_INDEX = 24; 050 private static final int RECEIVE_TIMESTAMP_INDEX = 32; 051 private static final int TRANSMIT_TIMESTAMP_INDEX = 40; 052 053 private static final int KEY_IDENTIFIER_INDEX = 48; 054 private static final int MESSAGE_DIGEST = 54; /* len 16 bytes */ 055 056 private byte[] buf = new byte[48]; 057 058 private DatagramPacket dp; 059 060 /** Creates a new instance of NtpV3Impl */ 061 public NtpV3Impl() 062 { 063 } 064 065 /*** 066 * Returns mode as defined in RFC-1305 which is a 3-bit integer 067 * whose value is indicated by the MODE_xxx parameters. 068 * 069 * @return mode as defined in RFC-1305. 070 */ 071 public int getMode() 072 { 073 return (ui(buf[MODE_INDEX]) >> MODE_SHIFT) & 0x7; 074 } 075 076 /*** 077 * Return human-readable name of message mode type as described in 078 * RFC 1305. 079 * @return mode name as string. 080 */ 081 public String getModeName() 082 { 083 return NtpUtils.getModeName(getMode()); 084 } 085 086 /*** 087 * Set mode as defined in RFC-1305. 088 * @param mode 089 */ 090 public void setMode(int mode) 091 { 092 buf[MODE_INDEX] = (byte) (buf[MODE_INDEX] & 0xF8 | mode & 0x7); 093 } 094 095 /*** 096 * Returns leap indicator as defined in RFC-1305 which is a two-bit code: 097 * 0=no warning 098 * 1=last minute has 61 seconds 099 * 2=last minute has 59 seconds 100 * 3=alarm condition (clock not synchronized) 101 * 102 * @return leap indicator as defined in RFC-1305. 103 */ 104 public int getLeapIndicator() 105 { 106 return (ui(buf[LI_INDEX]) >> LI_SHIFT) & 0x3; 107 } 108 109 /*** 110 * Set leap indicator as defined in RFC-1305. 111 * @param li leap indicator. 112 */ 113 public void setLeapIndicator(int li) 114 { 115 buf[LI_INDEX] = (byte) (buf[LI_INDEX] & 0x3F | ((li & 0x3) << LI_SHIFT)); 116 } 117 118 /*** 119 * Returns poll interval as defined in RFC-1305, which is an eight-bit 120 * signed integer indicating the maximum interval between successive 121 * messages, in seconds to the nearest power of two (e.g. value of six 122 * indicates an interval of 64 seconds. The values that can appear in 123 * this field range from NTP_MINPOLL to NTP_MAXPOLL inclusive. 124 * 125 * @return poll interval as defined in RFC-1305. 126 */ 127 public int getPoll() 128 { 129 return (int) (buf[POLL_INDEX]); 130 } 131 132 /*** 133 * Set poll interval as defined in RFC-1305. 134 * 135 * @param poll poll interval. 136 */ 137 public void setPoll(int poll) 138 { 139 buf[POLL_INDEX] = (byte) (poll & 0xFF); 140 } 141 142 /*** 143 * Returns precision as defined in RFC-1305 encoded as an 8-bit signed 144 * integer (seconds to nearest power of two). 145 * Values normally range from -6 to -20. 146 * 147 * @return precision as defined in RFC-1305. 148 */ 149 public int getPrecision() 150 { 151 return (int) buf[PRECISION_INDEX]; 152 } 153 154 /*** 155 * Set precision as defined in RFC-1305. 156 * @param precision 157 */ 158 public void setPrecision(int precision) 159 { 160 buf[PRECISION_INDEX] = (byte) (precision & 0xFF); 161 } 162 163 /*** 164 * Returns NTP version number as defined in RFC-1305. 165 * 166 * @return NTP version number. 167 */ 168 public int getVersion() 169 { 170 return (ui(buf[VERSION_INDEX]) >> VERSION_SHIFT) & 0x7; 171 } 172 173 /*** 174 * Set NTP version as defined in RFC-1305. 175 * 176 * @param version NTP version. 177 */ 178 public void setVersion(int version) 179 { 180 buf[VERSION_INDEX] = (byte) (buf[VERSION_INDEX] & 0xC7 | ((version & 0x7) << VERSION_SHIFT)); 181 } 182 183 /*** 184 * Returns Stratum as defined in RFC-1305, which indicates the stratum level 185 * of the local clock, with values defined as follows: 0=unspecified, 186 * 1=primary ref clock, and all others a secondary reference (via NTP). 187 * 188 * @return Stratum level as defined in RFC-1305. 189 */ 190 public int getStratum() 191 { 192 return ui(buf[STRATUM_INDEX]); 193 } 194 195 /*** 196 * Set stratum level as defined in RFC-1305. 197 * 198 * @param stratum stratum level. 199 */ 200 public void setStratum(int stratum) 201 { 202 buf[STRATUM_INDEX] = (byte) (stratum & 0xFF); 203 } 204 205 /*** 206 * Return root delay as defined in RFC-1305, which is the total roundtrip delay 207 * to the primary reference source, in seconds. Values can take positive and 208 * negative values, depending on clock precision and skew. 209 * 210 * @return root delay as defined in RFC-1305. 211 */ 212 public int getRootDelay() 213 { 214 return getInt(ROOT_DELAY_INDEX); 215 } 216 217 /*** 218 * Return root delay as defined in RFC-1305 in milliseconds, which is 219 * the total roundtrip delay to the primary reference source, in 220 * seconds. Values can take positive and negative values, depending 221 * on clock precision and skew. 222 * 223 * @return root delay in milliseconds 224 */ 225 public double getRootDelayInMillisDouble() 226 { 227 double l = getRootDelay(); 228 return l / 65.536; 229 } 230 231 /*** 232 * Returns root dispersion as defined in RFC-1305. 233 * @return root dispersion. 234 */ 235 public int getRootDispersion() 236 { 237 return getInt(ROOT_DISPERSION_INDEX); 238 } 239 240 /*** 241 * Returns root dispersion (as defined in RFC-1305) in milliseconds. 242 * 243 * @return root dispersion in milliseconds 244 */ 245 public long getRootDispersionInMillis() 246 { 247 long l = getRootDispersion(); 248 return (l * 1000) / 65536L; 249 } 250 251 /*** 252 * Returns root dispersion (as defined in RFC-1305) in milliseconds 253 * as double precision value. 254 * 255 * @return root dispersion in milliseconds 256 */ 257 public double getRootDispersionInMillisDouble() 258 { 259 double l = getRootDispersion(); 260 return l / 65.536; 261 } 262 263 /*** 264 * Set reference clock identifier field with 32-bit unsigned integer value. 265 * See RFC-1305 for description. 266 * 267 * @param refId reference clock identifier. 268 */ 269 public void setReferenceId(int refId) 270 { 271 for (int i = 3; i >= 0; i--) { 272 buf[REFERENCE_ID_INDEX + i] = (byte) (refId & 0xff); 273 refId >>>= 8; // shift right one-byte 274 } 275 } 276 277 /*** 278 * Returns the reference id as defined in RFC-1305, which is 279 * a 32-bit integer whose value is dependent on several criteria. 280 * 281 * @return the reference id as defined in RFC-1305. 282 */ 283 public int getReferenceId() 284 { 285 return getInt(REFERENCE_ID_INDEX); 286 } 287 288 /*** 289 * Returns the reference id string. String cannot be null but 290 * value is dependent on the version of the NTP spec supported 291 * and stratum level. Value can be an empty string, clock type string, 292 * IP address, or a hex string. 293 * 294 * @return the reference id string. 295 */ 296 public String getReferenceIdString() 297 { 298 int version = getVersion(); 299 int stratum = getStratum(); 300 if (version == VERSION_3 || version == VERSION_4) { 301 if (stratum == 0 || stratum == 1) { 302 return idAsString(); // 4-character ASCII string (e.g. GPS, USNO) 303 } 304 // in NTPv4 servers this is latest transmit timestamp of ref source 305 if (version == VERSION_4) 306 return idAsHex(); 307 } 308 309 // Stratum 2 and higher this is a four-octet IPv4 address 310 // of the primary reference host. 311 if (stratum >= 2) { 312 return idAsIPAddress(); 313 } 314 return idAsHex(); 315 } 316 317 /*** 318 * Returns Reference id as dotted IP address. 319 * @return refId as IP address string. 320 */ 321 private String idAsIPAddress() 322 { 323 return ui(buf[REFERENCE_ID_INDEX]) + "." + 324 ui(buf[REFERENCE_ID_INDEX + 1]) + "." + 325 ui(buf[REFERENCE_ID_INDEX + 2]) + "." + 326 ui(buf[REFERENCE_ID_INDEX + 3]); 327 } 328 329 private String idAsString() 330 { 331 String id = ""; 332 for (int i = 0; i <= 3; i++) { 333 char c = (char) buf[REFERENCE_ID_INDEX + i]; 334 if (c == 0) break; // 0-terminated string 335 id = id + c; 336 } 337 return id; 338 } 339 340 private String idAsHex() 341 { 342 return Integer.toHexString(getReferenceId()); 343 } 344 345 /*** 346 * Returns the transmit timestamp as defined in RFC-1305. 347 * 348 * @return the transmit timestamp as defined in RFC-1305. 349 * Never returns a null object. 350 */ 351 public TimeStamp getTransmitTimeStamp() 352 { 353 return getTimestamp(TRANSMIT_TIMESTAMP_INDEX); 354 } 355 356 /*** 357 * Set transmit time with NTP timestamp. 358 * If <code>ts</code> is null then zero time is used. 359 * 360 * @param ts NTP timestamp 361 */ 362 public void setTransmitTime(TimeStamp ts) 363 { 364 setTimestamp(TRANSMIT_TIMESTAMP_INDEX, ts); 365 } 366 367 /*** 368 * Set originate timestamp given NTP TimeStamp object. 369 * If <code>ts</code> is null then zero time is used. 370 * 371 * @param ts NTP timestamp 372 */ 373 public void setOriginateTimeStamp(TimeStamp ts) 374 { 375 setTimestamp(ORIGINATE_TIMESTAMP_INDEX, ts); 376 } 377 378 /*** 379 * Returns the originate time as defined in RFC-1305. 380 * 381 * @return the originate time. 382 * Never returns null. 383 */ 384 public TimeStamp getOriginateTimeStamp() 385 { 386 return getTimestamp(ORIGINATE_TIMESTAMP_INDEX); 387 } 388 389 /*** 390 * Returns the reference time as defined in RFC-1305. 391 * 392 * @return the reference time as <code>TimeStamp</code> object. 393 * Never returns null. 394 */ 395 public TimeStamp getReferenceTimeStamp() 396 { 397 return getTimestamp(REFERENCE_TIMESTAMP_INDEX); 398 } 399 400 /*** 401 * Set Reference time with NTP timestamp. If <code>ts</code> is null 402 * then zero time is used. 403 * 404 * @param ts NTP timestamp 405 */ 406 public void setReferenceTime(TimeStamp ts) 407 { 408 setTimestamp(REFERENCE_TIMESTAMP_INDEX, ts); 409 } 410 411 /*** 412 * Returns receive timestamp as defined in RFC-1305. 413 * 414 * @return the receive time. 415 * Never returns null. 416 */ 417 public TimeStamp getReceiveTimeStamp() 418 { 419 return getTimestamp(RECEIVE_TIMESTAMP_INDEX); 420 } 421 422 /*** 423 * Set receive timestamp given NTP TimeStamp object. 424 * If <code>ts</code> is null then zero time is used. 425 * 426 * @param ts timestamp 427 */ 428 public void setReceiveTimeStamp(TimeStamp ts) 429 { 430 setTimestamp(RECEIVE_TIMESTAMP_INDEX, ts); 431 } 432 433 /*** 434 * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...) 435 * correspond to the protocol used to obtain the timing information. 436 * 437 * @return packet type string identifier which in this case is "NTP". 438 */ 439 public String getType() 440 { 441 return "NTP"; 442 } 443 444 /*** 445 * @return 4 bytes as 32-bit int 446 */ 447 private int getInt(int index) 448 { 449 int i = ui(buf[index]) << 24 | 450 ui(buf[index + 1]) << 16 | 451 ui(buf[index + 2]) << 8 | 452 ui(buf[index + 3]); 453 454 return i; 455 } 456 457 /*** 458 * Get NTP Timestamp at specified starting index. 459 * 460 * @param index index into data array 461 * @return TimeStamp object for 64 bits starting at index 462 */ 463 private TimeStamp getTimestamp(int index) 464 { 465 return new TimeStamp(getLong(index)); 466 } 467 468 /*** 469 * Get Long value represented by bits starting at specified index. 470 * 471 * @return 8 bytes as 64-bit long 472 */ 473 private long getLong(int index) 474 { 475 long i = ul(buf[index]) << 56 | 476 ul(buf[index + 1]) << 48 | 477 ul(buf[index + 2]) << 40 | 478 ul(buf[index + 3]) << 32 | 479 ul(buf[index + 4]) << 24 | 480 ul(buf[index + 5]) << 16 | 481 ul(buf[index + 6]) << 8 | 482 ul(buf[index + 7]); 483 return i; 484 } 485 486 /*** 487 * Sets the NTP timestamp at the given array index. 488 * 489 * @param index index into the byte array. 490 * @param t TimeStamp. 491 */ 492 private void setTimestamp(int index, TimeStamp t) 493 { 494 long ntpTime = (t == null) ? 0 : t.ntpValue(); 495 // copy 64-bits from Long value into 8 x 8-bit bytes of array 496 // one byte at a time shifting 8-bits for each position. 497 for (int i = 7; i >= 0; i--) { 498 buf[index + i] = (byte) (ntpTime & 0xFF); 499 ntpTime >>>= 8; // shift to next byte 500 } 501 // buf[index] |= 0x80; // only set if 1900 baseline.... 502 } 503 504 /*** 505 * Returns the datagram packet with the NTP details already filled in. 506 * 507 * @return a datagram packet. 508 */ 509 public DatagramPacket getDatagramPacket() 510 { 511 if (dp == null) 512 synchronized(this) { 513 if (dp == null) { 514 dp = new DatagramPacket(buf, buf.length); 515 dp.setPort(NTP_PORT); 516 } 517 } 518 return dp; 519 } 520 521 /*** 522 * Set the contents of this object from source datagram packet. 523 * 524 * @param srcDp source DatagramPacket to copy contents from. 525 */ 526 public void setDatagramPacket(DatagramPacket srcDp) 527 { 528 byte[] incomingBuf = srcDp.getData(); 529 int len = srcDp.getLength(); 530 if (len > buf.length) 531 len = buf.length; 532 533 System.arraycopy(incomingBuf, 0, buf, 0, len); 534 } 535 536 /*** 537 * Convert byte to unsigned integer. 538 * Java only has signed types so we have to do 539 * more work to get unsigned ops. 540 * 541 * @param b 542 * @return unsigned int value of byte 543 */ 544 protected final static int ui(byte b) 545 { 546 int i = b & 0xFF; 547 return i; 548 } 549 550 /*** 551 * Convert byte to unsigned long. 552 * Java only has signed types so we have to do 553 * more work to get unsigned ops 554 * 555 * @param b 556 * @return unsigned long value of byte 557 */ 558 protected final static long ul(byte b) 559 { 560 long i = b & 0xFF; 561 return i; 562 } 563 564 /*** 565 * Returns details of NTP packet as a string. 566 * 567 * @return details of NTP packet as a string. 568 */ 569 public String toString() 570 { 571 return "[" + 572 "version:" + getVersion() + 573 ", mode:" + getMode() + 574 ", poll:" + getPoll() + 575 ", precision:" + getPrecision() + 576 ", delay:" + getRootDelay() + 577 ", dispersion(ms):" + getRootDispersionInMillisDouble() + 578 ", id:" + getReferenceIdString() + 579 ", xmitTime:" + getTransmitTimeStamp().toDateString() + 580 " ]"; 581 } 582 583 }