1 /* 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that: (1) source code 4 * distributions retain the above copyright notice and this paragraph 5 * in its entirety, and (2) distributions including binary code include 6 * the above copyright notice and this paragraph in its entirety in 7 * the documentation or other materials provided with the distribution. 8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 11 * FOR A PARTICULAR PURPOSE. 12 * 13 * Original code by Partha S. Ghosh (psglinux dot gmail dot com) 14 */ 15 16 /* \summary: Precision Time Protocol (PTP) printer */ 17 18 /* specification: https://standards.ieee.org/findstds/standard/1588-2008.html*/ 19 20 #include <config.h> 21 22 #include "netdissect-stdinc.h" 23 #include "netdissect.h" 24 #include "extract.h" 25 26 /* 27 * PTP header 28 * 0 1 2 3 29 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 30 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 31 * | R | |msgtype| version | Msg Len | 32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 33 * | domain No | rsvd1 | flag Field | 34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 35 * | Correction NS | 36 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 37 * | | Correction Sub NS | 38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 39 * | Reserved2 | 40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 41 * | Clock Identity | 42 * | | 43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44 * | Port Identity | Sequence ID | 45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 46 * | control | log msg int | 47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 48 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 49 * 0 1 2 3 50 * 51 * Announce Message (msg type=0xB) 52 * 0 1 2 3 53 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 55 * | | 56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 57 * | Seconds | 58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 59 * | Nano Seconds | 60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 61 * | Origin Cur UTC Offset | Reserved | GM Prio 1 | 62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 63 * |GM Clock Class | GM Clock Accu | GM Clock Variance | 64 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 65 * | GM Prio 2 | | 66 * +-+-+-+-+-+-+-+-+ + 67 * | GM Clock Identity | 68 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 69 * | | Steps Removed | Time Source | 70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 71 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 72 * 0 1 2 3 73 * 74 * Sync Message (msg type=0x0) 75 * 0 1 2 3 76 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 77 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 78 * | | 79 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 80 * | Seconds | 81 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 82 * | Nano Seconds | 83 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 84 * 85 * Delay Request Message (msg type=0x1) 86 * 0 1 2 3 87 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 88 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 89 * | | 90 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 91 * | Origin Time Stamp Seconds | 92 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 93 * | Nano Seconds | 94 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 95 * 96 * Followup Message (msg type=0x8) 97 * 0 1 2 3 98 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 99 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 100 * | | 101 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 102 * | Precise Origin Time Stamp Seconds | 103 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 104 * | Nano Seconds | 105 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 106 * 107 * Delay Resp Message (msg type=0x9) 108 * 0 1 2 3 109 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 110 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 111 * | | 112 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 113 * | Seconds | 114 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 115 * | Nano Seconds | 116 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 117 * | Port Identity | 118 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 119 * 120 * PDelay Request Message (msg type=0x2) 121 * 0 1 2 3 122 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 123 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 124 * | | 125 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 126 * | Origin Time Stamp Seconds | 127 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 128 * | Origin Time Stamp Nano Seconds | 129 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 130 * | Port Identity | 131 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 132 * 133 * PDelay Response Message (msg type=0x3) 134 * 0 1 2 3 135 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 136 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 137 * | | 138 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 139 * | Request receipt Time Stamp Seconds | 140 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 141 * | Nano Seconds | 142 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 143 * | Requesting Port Identity | 144 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 145 * 146 * PDelay Resp Follow up Message (msg type=0xA) 147 * 0 1 2 3 148 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 149 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 150 * | | 151 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 152 * | Response Origin Time Stamp Seconds | 153 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 154 * | Nano Seconds | 155 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 156 * | Requesting Port Identity | 157 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 158 * 159 * Signaling Message (msg type=0xC) 160 * 0 1 2 3 161 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 162 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 163 * | Requesting Port Identity | 164 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 165 * 166 * Management Message (msg type=0xD) 167 * 0 1 2 3 168 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 169 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 170 * | Requesting Port Identity | 171 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 172 * |Start Bndry Hps| Boundary Hops | flags | Reserved | 173 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 174 * 175 */ 176 177 /* Values from IEEE1588-2008: 13.3.2.2 messageType (Enumeration4) */ 178 #define M_SYNC 0x0 179 #define M_DELAY_REQ 0x1 180 #define M_PDELAY_REQ 0x2 181 #define M_PDELAY_RESP 0x3 182 #define M_FOLLOW_UP 0x8 183 #define M_DELAY_RESP 0x9 184 #define M_PDELAY_RESP_FOLLOW_UP 0xA 185 #define M_ANNOUNCE 0xB 186 #define M_SIGNALING 0xC 187 #define M_MANAGEMENT 0xD 188 189 static const struct tok ptp_msg_type[] = { 190 { M_SYNC, "sync msg"}, 191 { M_DELAY_REQ, "delay req msg"}, 192 { M_PDELAY_REQ, "peer delay req msg"}, 193 { M_PDELAY_RESP, "peer delay resp msg"}, 194 { M_FOLLOW_UP, "follow up msg"}, 195 { M_DELAY_RESP, "delay resp msg"}, 196 { M_PDELAY_RESP_FOLLOW_UP, "pdelay resp fup msg"}, 197 { M_ANNOUNCE, "announce msg"}, 198 { M_SIGNALING, "signaling msg"}, 199 { M_MANAGEMENT, "management msg"}, 200 { 0, NULL} 201 }; 202 203 /* Values from IEEE1588-2008: 13.3.2.10 controlField (UInteger8) */ 204 /* 205 * The use of this field by the receiver is deprecated. 206 * NOTE-This field is provided for compatibility with hardware designed 207 * to conform to version 1 of this standard. 208 */ 209 #define C_SYNC 0x0 210 #define C_DELAY_REQ 0x1 211 #define C_FOLLOW_UP 0x2 212 #define C_DELAY_RESP 0x3 213 #define C_MANAGEMENT 0x4 214 #define C_OTHER 0x5 215 216 static const struct tok ptp_control_field[] = { 217 { C_SYNC, "Sync"}, 218 { C_DELAY_REQ, "Delay_Req"}, 219 { C_FOLLOW_UP, "Follow_Up"}, 220 { C_DELAY_RESP, "Delay_Resp"}, 221 { C_MANAGEMENT, "Management"}, 222 { C_OTHER, "Other"}, 223 { 0, NULL} 224 }; 225 226 #define PTP_TRUE 1 227 #define PTP_FALSE !PTP_TRUE 228 229 #define PTP_HDR_LEN 0x22 230 231 /* mask based on the first byte */ 232 #define PTP_MAJOR_VERS_MASK 0x0F 233 #define PTP_MINOR_VERS_MASK 0xF0 234 #define PTP_MAJOR_SDO_ID_MASK 0xF0 235 #define PTP_MSG_TYPE_MASK 0x0F 236 237 /*mask based 2byte */ 238 #define PTP_DOMAIN_MASK 0xFF00 239 #define PTP_RSVD1_MASK 0xFF 240 #define PTP_CONTROL_MASK 0xFF 241 #define PTP_LOGMSG_MASK 0xFF 242 243 /* mask based on the flags 2 bytes */ 244 245 #define PTP_L161_MASK 0x1 246 #define PTP_L1_59_MASK 0x2 247 #define PTP_UTC_REASONABLE_MASK 0x4 248 #define PTP_TIMESCALE_MASK 0x8 249 #define PTP_TIME_TRACABLE_MASK 0x10 250 #define PTP_FREQUENCY_TRACABLE_MASK 0x20 251 #define PTP_ALTERNATE_MASTER_MASK 0x100 252 #define PTP_TWO_STEP_MASK 0x200 253 #define PTP_UNICAST_MASK 0x400 254 #define PTP_PROFILE_SPEC_1_MASK 0x1000 255 #define PTP_PROFILE_SPEC_2_MASK 0x2000 256 #define PTP_SECURITY_MASK 0x4000 257 #define PTP_FLAGS_UNKNOWN_MASK 0x18C0 258 259 static const struct tok ptp_flag_values[] = { 260 { PTP_L161_MASK, "l1 61"}, 261 { PTP_L1_59_MASK, "l1 59"}, 262 { PTP_UTC_REASONABLE_MASK, "utc reasonable"}, 263 { PTP_TIMESCALE_MASK, "timescale"}, 264 { PTP_TIME_TRACABLE_MASK, "time tracable"}, 265 { PTP_FREQUENCY_TRACABLE_MASK, "frequency tracable"}, 266 { PTP_ALTERNATE_MASTER_MASK, "alternate master"}, 267 { PTP_TWO_STEP_MASK, "two step"}, 268 { PTP_UNICAST_MASK, "unicast"}, 269 { PTP_PROFILE_SPEC_1_MASK, "profile specific 1"}, 270 { PTP_PROFILE_SPEC_2_MASK, "profile specific 2"}, 271 { PTP_SECURITY_MASK, "security mask"}, 272 { PTP_FLAGS_UNKNOWN_MASK, "unknown"}, 273 {0, NULL} 274 }; 275 276 static const char *p_porigin_ts = "preciseOriginTimeStamp"; 277 static const char *p_origin_ts = "originTimeStamp"; 278 static const char *p_recv_ts = "receiveTimeStamp"; 279 280 #define PTP_VER_1 0x1 281 #define PTP_VER_2 0x2 282 283 #define PTP_UCHAR_LEN sizeof(uint8_t) 284 #define PTP_UINT16_LEN sizeof(uint16_t) 285 #define PTP_UINT32_LEN sizeof(uint32_t) 286 #define PTP_6BYTES_LEN sizeof(uint32_t)+sizeof(uint16_t) 287 #define PTP_UINT64_LEN sizeof(uint64_t) 288 289 static void ptp_print_1(netdissect_options *ndo); 290 static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int len); 291 292 static void ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype); 293 static void ptp_print_timestamp_identity(netdissect_options *ndo, const u_char *bp, u_int *len, const char *ttype); 294 static void ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len); 295 static const u_char *ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len); 296 static void ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len); 297 298 static const u_char * 299 print_field(netdissect_options *ndo, const char *st, uint32_t flen, 300 const u_char *bp, u_int *len, uint8_t hex) 301 { 302 uint8_t u8_val; 303 uint16_t u16_val; 304 uint32_t u32_val; 305 uint64_t u64_val; 306 307 switch(flen) { 308 case PTP_UCHAR_LEN: 309 u8_val = GET_U_1(bp); 310 ND_PRINT(", %s", st); 311 if (hex) 312 ND_PRINT(" 0x%x", u8_val); 313 else 314 ND_PRINT(" %u", u8_val); 315 *len -= 1; bp += 1; 316 break; 317 case PTP_UINT16_LEN: 318 u16_val = GET_BE_U_2(bp); 319 ND_PRINT(", %s", st); 320 if (hex) 321 ND_PRINT(" 0x%x", u16_val); 322 else 323 ND_PRINT(" %u", u16_val); 324 *len -= 2; bp += 2; 325 break; 326 case PTP_UINT32_LEN: 327 u32_val = GET_BE_U_4(bp); 328 ND_PRINT(", %s", st); 329 if (hex) 330 ND_PRINT(" 0x%x", u32_val); 331 else 332 ND_PRINT(" %u", u32_val); 333 *len -= 4; bp += 4; 334 break; 335 case PTP_UINT64_LEN: 336 u64_val = GET_BE_U_8(bp); 337 ND_PRINT(", %s", st); 338 if (hex) 339 ND_PRINT(" 0x%"PRIx64, u64_val); 340 else 341 ND_PRINT(" 0x%"PRIu64, u64_val); 342 *len -= 8; bp += 8; 343 break; 344 default: 345 break; 346 } 347 348 return bp; 349 } 350 351 static void 352 ptp_print_1(netdissect_options *ndo) 353 { 354 ND_PRINT(" (not implemented)"); 355 } 356 357 static void 358 ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length) 359 { 360 u_int len = length; 361 uint16_t msg_len, flags, port_id, seq_id; 362 uint8_t foct, domain_no, msg_type, major_sdo_id, rsvd1, lm_int, control; 363 uint64_t ns_corr; 364 uint16_t sns_corr; 365 uint32_t rsvd2; 366 uint64_t clk_id; 367 368 foct = GET_U_1(bp); 369 major_sdo_id = (foct & PTP_MAJOR_SDO_ID_MASK) >> 4; 370 ND_PRINT(", majorSdoId: 0x%x", major_sdo_id); 371 msg_type = foct & PTP_MSG_TYPE_MASK; 372 ND_PRINT(", msg type: %s", tok2str(ptp_msg_type, "Reserved", msg_type)); 373 374 /* msg length */ 375 len -= 2; bp += 2; msg_len = GET_BE_U_2(bp); ND_PRINT(", length: %u", msg_len); 376 377 /* domain */ 378 len -= 2; bp += 2; domain_no = (GET_BE_U_2(bp) & PTP_DOMAIN_MASK) >> 8; ND_PRINT(", domain: %u", domain_no); 379 380 /* rsvd 1*/ 381 rsvd1 = GET_BE_U_2(bp) & PTP_RSVD1_MASK; 382 ND_PRINT(", reserved1: %u", rsvd1); 383 384 /* flags */ 385 len -= 2; bp += 2; flags = GET_BE_U_2(bp); ND_PRINT(", Flags [%s]", bittok2str(ptp_flag_values, "none", flags)); 386 387 /* correction NS (48 bits) */ 388 len -= 2; bp += 2; ns_corr = GET_BE_U_6(bp); ND_PRINT(", NS correction: %"PRIu64, ns_corr); 389 390 /* correction sub NS (16 bits) */ 391 len -= 6; bp += 6; sns_corr = GET_BE_U_2(bp); ND_PRINT(", sub NS correction: %u", sns_corr); 392 393 /* Reserved 2 */ 394 len -= 2; bp += 2; rsvd2 = GET_BE_U_4(bp); ND_PRINT(", reserved2: %u", rsvd2); 395 396 /* clock identity */ 397 len -= 4; bp += 4; clk_id = GET_BE_U_8(bp); ND_PRINT(", clock identity: 0x%"PRIx64, clk_id); 398 399 /* port identity */ 400 len -= 8; bp += 8; port_id = GET_BE_U_2(bp); ND_PRINT(", port id: %u", port_id); 401 402 /* sequence ID */ 403 len -= 2; bp += 2; seq_id = GET_BE_U_2(bp); ND_PRINT(", seq id: %u", seq_id); 404 405 /* control */ 406 len -= 2; bp += 2; control = GET_U_1(bp) ; 407 ND_PRINT(", control: %u (%s)", control, tok2str(ptp_control_field, "Reserved", control)); 408 409 /* log message interval */ 410 lm_int = GET_BE_U_2(bp) & PTP_LOGMSG_MASK; ND_PRINT(", log message interval: %u", lm_int); len -= 2; bp += 2; 411 412 switch(msg_type) { 413 case M_SYNC: 414 ptp_print_timestamp(ndo, bp, &len, p_origin_ts); 415 break; 416 case M_DELAY_REQ: 417 ptp_print_timestamp(ndo, bp, &len, p_origin_ts); 418 break; 419 case M_PDELAY_REQ: 420 ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts); 421 break; 422 case M_PDELAY_RESP: 423 ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts); 424 break; 425 case M_FOLLOW_UP: 426 ptp_print_timestamp(ndo, bp, &len, p_porigin_ts); 427 break; 428 case M_DELAY_RESP: 429 ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts); 430 break; 431 case M_PDELAY_RESP_FOLLOW_UP: 432 ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts); 433 break; 434 case M_ANNOUNCE: 435 ptp_print_announce_msg(ndo, bp, &len); 436 break; 437 case M_SIGNALING: 438 ptp_print_port_id(ndo, bp, &len); 439 break; 440 case M_MANAGEMENT: 441 ptp_print_mgmt_msg(ndo, bp, &len); 442 break; 443 default: 444 break; 445 } 446 } 447 /* 448 * PTP general message 449 */ 450 void 451 ptp_print(netdissect_options *ndo, const u_char *bp, u_int length) 452 { 453 u_int major_vers; 454 u_int minor_vers; 455 456 /* In 1588-2019, a minorVersionPTP field has been created in the common PTP 457 * message header, from a previously reserved field. Implementations 458 * compatible to the 2019 edition shall indicate a versionPTP field value 459 * of 2 and minorVersionPTP field value of 1, indicating that this is PTP 460 * version 2.1. 461 */ 462 ndo->ndo_protocol = "ptp"; 463 ND_ICHECK_U(length, <, PTP_HDR_LEN); 464 major_vers = GET_BE_U_2(bp) & PTP_MAJOR_VERS_MASK; 465 minor_vers = (GET_BE_U_2(bp) & PTP_MINOR_VERS_MASK) >> 4; 466 if (minor_vers) 467 ND_PRINT("PTPv%u.%u", major_vers, minor_vers); 468 else 469 ND_PRINT("PTPv%u", major_vers); 470 471 switch(major_vers) { 472 case PTP_VER_1: 473 ptp_print_1(ndo); 474 break; 475 case PTP_VER_2: 476 ptp_print_2(ndo, bp, length); 477 break; 478 default: 479 //ND_PRINT("ERROR: unknown-version\n"); 480 break; 481 } 482 return; 483 484 invalid: 485 nd_print_invalid(ndo); 486 } 487 488 static void 489 ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype) 490 { 491 uint64_t secs; 492 uint32_t nsecs; 493 494 ND_PRINT(", %s:", stype); 495 /* sec time stamp 6 bytes */ 496 secs = GET_BE_U_6(bp); 497 ND_PRINT(" %"PRIu64" seconds,", secs); 498 *len -= 6; 499 bp += 6; 500 501 /* NS time stamp 4 bytes */ 502 nsecs = GET_BE_U_4(bp); 503 ND_PRINT(" %u nanoseconds", nsecs); 504 *len -= 4; 505 bp += 4; 506 } 507 static void 508 ptp_print_timestamp_identity(netdissect_options *ndo, 509 const u_char *bp, u_int *len, const char *ttype) 510 { 511 uint64_t secs; 512 uint32_t nsecs; 513 uint16_t port_id; 514 uint64_t port_identity; 515 516 ND_PRINT(", %s:", ttype); 517 /* sec time stamp 6 bytes */ 518 secs = GET_BE_U_6(bp); 519 ND_PRINT(" %"PRIu64" seconds,", secs); 520 *len -= 6; 521 bp += 6; 522 523 /* NS time stamp 4 bytes */ 524 nsecs = GET_BE_U_4(bp); 525 ND_PRINT(" %u nanoseconds", nsecs); 526 *len -= 4; 527 bp += 4; 528 529 /* port identity*/ 530 port_identity = GET_BE_U_8(bp); 531 ND_PRINT(", port identity: 0x%"PRIx64, port_identity); 532 *len -= 8; 533 bp += 8; 534 535 /* port id */ 536 port_id = GET_BE_U_2(bp); 537 ND_PRINT(", port id: %u", port_id); 538 *len -= 2; 539 bp += 2; 540 } 541 static void 542 ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len) 543 { 544 uint8_t rsvd, gm_prio_1, gm_prio_2, gm_clk_cls, gm_clk_acc, time_src; 545 uint16_t origin_cur_utc, gm_clk_var, steps_removed; 546 uint64_t gm_clock_id; 547 uint64_t secs; 548 uint32_t nsecs; 549 550 ND_PRINT(", %s:", p_origin_ts); 551 /* sec time stamp 6 bytes */ 552 secs = GET_BE_U_6(bp); 553 ND_PRINT(" %"PRIu64" seconds", secs); 554 *len -= 6; 555 bp += 6; 556 557 /* NS time stamp 4 bytes */ 558 nsecs = GET_BE_U_4(bp); 559 ND_PRINT(" %u nanoseconds", nsecs); 560 *len -= 4; 561 bp += 4; 562 563 /* origin cur utc */ 564 origin_cur_utc = GET_BE_U_2(bp); 565 ND_PRINT(", origin cur utc:%u", origin_cur_utc); 566 *len -= 2; 567 bp += 2; 568 569 /* rsvd */ 570 rsvd = GET_U_1(bp); 571 ND_PRINT(", rsvd: %u", rsvd); 572 *len -= 1; 573 bp += 1; 574 575 /* gm prio */ 576 gm_prio_1 = GET_U_1(bp); 577 ND_PRINT(", gm priority_1: %u", gm_prio_1); 578 *len -= 1; 579 bp += 1; 580 581 /* GM clock class */ 582 gm_clk_cls = GET_U_1(bp); 583 ND_PRINT(", gm clock class: %u", gm_clk_cls); 584 *len -= 1; 585 bp += 1; 586 /* GM clock accuracy */ 587 gm_clk_acc = GET_U_1(bp); 588 ND_PRINT(", gm clock accuracy: %u", gm_clk_acc); 589 *len -= 1; 590 bp += 1; 591 /* GM clock variance */ 592 gm_clk_var = GET_BE_U_2(bp); 593 ND_PRINT(", gm clock variance: %u", gm_clk_var); 594 *len -= 2; 595 bp += 2; 596 /* GM Prio 2 */ 597 gm_prio_2 = GET_U_1(bp); 598 ND_PRINT(", gm priority_2: %u", gm_prio_2); 599 *len -= 1; 600 bp += 1; 601 602 /* GM Clock Identity */ 603 gm_clock_id = GET_BE_U_8(bp); 604 ND_PRINT(", gm clock id: 0x%"PRIx64, gm_clock_id); 605 *len -= 8; 606 bp += 8; 607 /* steps removed */ 608 steps_removed = GET_BE_U_2(bp); 609 ND_PRINT(", steps removed: %u", steps_removed); 610 *len -= 2; 611 bp += 2; 612 /* Time source */ 613 time_src = GET_U_1(bp); 614 ND_PRINT(", time source: 0x%x", time_src); 615 *len -= 1; 616 bp += 1; 617 618 } 619 620 static const u_char * 621 ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len) 622 { 623 uint16_t port_id; 624 uint64_t port_identity; 625 626 /* port identity*/ 627 port_identity = GET_BE_U_8(bp); 628 ND_PRINT(", port identity: 0x%"PRIx64, port_identity); 629 *len -= 8; 630 bp += 8; 631 632 /* port id */ 633 port_id = GET_BE_U_2(bp); 634 ND_PRINT(", port id: %u", port_id); 635 *len -= 2; 636 bp += 2; 637 638 return bp; 639 } 640 641 static void 642 ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len) 643 { 644 bp = ptp_print_port_id(ndo, bp, len); 645 bp = print_field(ndo, "start boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE); 646 bp = print_field(ndo, "boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE); 647 bp = print_field(ndo, "flags:", PTP_UCHAR_LEN, bp, len, PTP_TRUE); 648 bp = print_field(ndo, "reserved:", PTP_UCHAR_LEN, bp, len, PTP_TRUE); 649 } 650