1 /* 2 * Copyright (c) 2009 3 * Siemens AG, All rights reserved. 4 * Dmitry Eremin-Solenikov (dbaryshkov@gmail.com) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that: (1) source code distributions 8 * retain the above copyright notice and this paragraph in its entirety, (2) 9 * distributions including binary code include the above copyright notice and 10 * this paragraph in its entirety in the documentation or other materials 11 * provided with the distribution, and (3) all advertising materials mentioning 12 * features or use of this software display the following acknowledgement: 13 * ``This product includes software developed by the University of California, 14 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 15 * the University nor the names of its contributors may be used to endorse 16 * or promote products derived from this software without specific prior 17 * written permission. 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21 */ 22 23 /* \summary: IEEE 802.15.4 printer */ 24 25 #ifdef HAVE_CONFIG_H 26 #include <config.h> 27 #endif 28 29 #include "netdissect-stdinc.h" 30 31 #define ND_LONGJMP_FROM_TCHECK 32 #include "netdissect.h" 33 #include "addrtoname.h" 34 35 #include "extract.h" 36 37 #define CHECK_BIT(num,bit) (((num) >> (bit)) & 0x1) 38 39 #define BROKEN_6TISCH_PAN_ID_COMPRESSION 0 40 41 /* Frame types from Table 7-1 of 802.15.4-2015 */ 42 static const char *ftypes[] = { 43 "Beacon", /* 0 */ 44 "Data", /* 1 */ 45 "ACK", /* 2 */ 46 "Command", /* 3 */ 47 "Reserved", /* 4 */ 48 "Multipurpose", /* 5 */ 49 "Fragment", /* 6 */ 50 "Extended" /* 7 */ 51 }; 52 53 /* Element IDs for Header IEs from Table 7-7 of 802.15.4-2015 */ 54 static const char *h_ie_names[] = { 55 "Vendor Specific Header IE", /* 0x00 */ 56 "Reserved 0x01", /* 0x01 */ 57 "Reserved 0x02", /* 0x02 */ 58 "Reserved 0x03", /* 0x03 */ 59 "Reserved 0x04", /* 0x04 */ 60 "Reserved 0x05", /* 0x05 */ 61 "Reserved 0x06", /* 0x06 */ 62 "Reserved 0x07", /* 0x07 */ 63 "Reserved 0x08", /* 0x08 */ 64 "Reserved 0x09", /* 0x09 */ 65 "Reserved 0x0a", /* 0x0a */ 66 "Reserved 0x0b", /* 0x0b */ 67 "Reserved 0x0c", /* 0x0c */ 68 "Reserved 0x0d", /* 0x0d */ 69 "Reserved 0x0e", /* 0x0e */ 70 "Reserved 0x0f", /* 0x0f */ 71 "Reserved 0x10", /* 0x10 */ 72 "Reserved 0x11", /* 0x11 */ 73 "Reserved 0x12", /* 0x12 */ 74 "Reserved 0x13", /* 0x13 */ 75 "Reserved 0x14", /* 0x14 */ 76 "Reserved 0x15", /* 0x15 */ 77 "Reserved 0x16", /* 0x16 */ 78 "Reserved 0x17", /* 0x17 */ 79 "Reserved 0x18", /* 0x18 */ 80 "Reserved 0x19", /* 0x19 */ 81 "LE CSL IE", /* 0x1a */ 82 "LE RIT IE", /* 0x1b */ 83 "DSME PAN descriptor IE", /* 0x1c */ 84 "Rendezvous Time IE", /* 0x1d */ 85 "Time Correction IE", /* 0x1e */ 86 "Reserved 0x1f", /* 0x1f */ 87 "Reserved 0x20", /* 0x20 */ 88 "Extended DSME PAN descriptor IE", /* 0x21 */ 89 "Fragment Sequence Context Description IE", /* 0x22 */ 90 "Simplified Superframe Specification IE", /* 0x23 */ 91 "Simplified GTS Specification IE", /* 0x24 */ 92 "LECIM Capabilities IE", /* 0x25 */ 93 "TRLE Descriptor IE", /* 0x26 */ 94 "RCC Capabilities IE", /* 0x27 */ 95 "RCCN Descriptor IE", /* 0x28 */ 96 "Global Time IE", /* 0x29 */ 97 "Omnibus Header IE", /* 0x2a */ 98 "DA IE", /* 0x2b */ 99 "Reserved 0x2c", /* 0x2c */ 100 "Reserved 0x2d", /* 0x2d */ 101 "Reserved 0x2e", /* 0x2e */ 102 "Reserved 0x2f", /* 0x2f */ 103 "Reserved 0x30", /* 0x30 */ 104 "Reserved 0x31", /* 0x31 */ 105 "Reserved 0x32", /* 0x32 */ 106 "Reserved 0x33", /* 0x33 */ 107 "Reserved 0x34", /* 0x34 */ 108 "Reserved 0x35", /* 0x35 */ 109 "Reserved 0x36", /* 0x36 */ 110 "Reserved 0x37", /* 0x37 */ 111 "Reserved 0x38", /* 0x38 */ 112 "Reserved 0x39", /* 0x39 */ 113 "Reserved 0x3a", /* 0x3a */ 114 "Reserved 0x3b", /* 0x3b */ 115 "Reserved 0x3c", /* 0x3c */ 116 "Reserved 0x3d", /* 0x3d */ 117 "Reserved 0x3e", /* 0x3e */ 118 "Reserved 0x3f", /* 0x3f */ 119 "Reserved 0x40", /* 0x40 */ 120 "Reserved 0x41", /* 0x41 */ 121 "Reserved 0x42", /* 0x42 */ 122 "Reserved 0x43", /* 0x43 */ 123 "Reserved 0x44", /* 0x44 */ 124 "Reserved 0x45", /* 0x45 */ 125 "Reserved 0x46", /* 0x46 */ 126 "Reserved 0x47", /* 0x47 */ 127 "Reserved 0x48", /* 0x48 */ 128 "Reserved 0x49", /* 0x49 */ 129 "Reserved 0x4a", /* 0x4a */ 130 "Reserved 0x4b", /* 0x4b */ 131 "Reserved 0x4c", /* 0x4c */ 132 "Reserved 0x4d", /* 0x4d */ 133 "Reserved 0x4e", /* 0x4e */ 134 "Reserved 0x4f", /* 0x4f */ 135 "Reserved 0x50", /* 0x50 */ 136 "Reserved 0x51", /* 0x51 */ 137 "Reserved 0x52", /* 0x52 */ 138 "Reserved 0x53", /* 0x53 */ 139 "Reserved 0x54", /* 0x54 */ 140 "Reserved 0x55", /* 0x55 */ 141 "Reserved 0x56", /* 0x56 */ 142 "Reserved 0x57", /* 0x57 */ 143 "Reserved 0x58", /* 0x58 */ 144 "Reserved 0x59", /* 0x59 */ 145 "Reserved 0x5a", /* 0x5a */ 146 "Reserved 0x5b", /* 0x5b */ 147 "Reserved 0x5c", /* 0x5c */ 148 "Reserved 0x5d", /* 0x5d */ 149 "Reserved 0x5e", /* 0x5e */ 150 "Reserved 0x5f", /* 0x5f */ 151 "Reserved 0x60", /* 0x60 */ 152 "Reserved 0x61", /* 0x61 */ 153 "Reserved 0x62", /* 0x62 */ 154 "Reserved 0x63", /* 0x63 */ 155 "Reserved 0x64", /* 0x64 */ 156 "Reserved 0x65", /* 0x65 */ 157 "Reserved 0x66", /* 0x66 */ 158 "Reserved 0x67", /* 0x67 */ 159 "Reserved 0x68", /* 0x68 */ 160 "Reserved 0x69", /* 0x69 */ 161 "Reserved 0x6a", /* 0x6a */ 162 "Reserved 0x6b", /* 0x6b */ 163 "Reserved 0x6c", /* 0x6c */ 164 "Reserved 0x6d", /* 0x6d */ 165 "Reserved 0x6e", /* 0x6e */ 166 "Reserved 0x6f", /* 0x6f */ 167 "Reserved 0x70", /* 0x70 */ 168 "Reserved 0x71", /* 0x71 */ 169 "Reserved 0x72", /* 0x72 */ 170 "Reserved 0x73", /* 0x73 */ 171 "Reserved 0x74", /* 0x74 */ 172 "Reserved 0x75", /* 0x75 */ 173 "Reserved 0x76", /* 0x76 */ 174 "Reserved 0x77", /* 0x77 */ 175 "Reserved 0x78", /* 0x78 */ 176 "Reserved 0x79", /* 0x79 */ 177 "Reserved 0x7a", /* 0x7a */ 178 "Reserved 0x7b", /* 0x7b */ 179 "Reserved 0x7c", /* 0x7c */ 180 "Reserved 0x7d", /* 0x7d */ 181 "Header Termination 1 IE", /* 0x7e */ 182 "Header Termination 2 IE" /* 0x7f */ 183 }; 184 185 /* Payload IE Group IDs from Table 7-15 of 802.15.4-2015 */ 186 static const char *p_ie_names[] = { 187 "ESDU IE", /* 0x00 */ 188 "MLME IE", /* 0x01 */ 189 "Vendor Specific Nested IE", /* 0x02 */ 190 "Multiplexed IE (802.15.9)", /* 0x03 */ 191 "Omnibus Payload Group IE", /* 0x04 */ 192 "IETF IE", /* 0x05 */ 193 "Reserved 0x06", /* 0x06 */ 194 "Reserved 0x07", /* 0x07 */ 195 "Reserved 0x08", /* 0x08 */ 196 "Reserved 0x09", /* 0x09 */ 197 "Reserved 0x0a", /* 0x0a */ 198 "Reserved 0x0b", /* 0x0b */ 199 "Reserved 0x0c", /* 0x0c */ 200 "Reserved 0x0d", /* 0x0d */ 201 "Reserved 0x0e", /* 0x0e */ 202 "List termination" /* 0x0f */ 203 }; 204 205 /* Sub-ID for short format from Table 7-16 of 802.15.4-2015 */ 206 static const char *p_mlme_short_names[] = { 207 "Reserved for long format 0x0", /* 0x00 */ 208 "Reserved for long format 0x1", /* 0x01 */ 209 "Reserved for long format 0x2", /* 0x02 */ 210 "Reserved for long format 0x3", /* 0x03 */ 211 "Reserved for long format 0x4", /* 0x04 */ 212 "Reserved for long format 0x5", /* 0x05 */ 213 "Reserved for long format 0x6", /* 0x06 */ 214 "Reserved for long format 0x7", /* 0x07 */ 215 "Reserved for long format 0x8", /* 0x08 */ 216 "Reserved for long format 0x9", /* 0x09 */ 217 "Reserved for long format 0xa", /* 0x0a */ 218 "Reserved for long format 0xb", /* 0x0b */ 219 "Reserved for long format 0xc", /* 0x0c */ 220 "Reserved for long format 0xd", /* 0x0d */ 221 "Reserved for long format 0xe", /* 0x0e */ 222 "Reserved for long format 0xf", /* 0x0f */ 223 "Reserved 0x10", /* 0x10 */ 224 "Reserved 0x11", /* 0x11 */ 225 "Reserved 0x12", /* 0x12 */ 226 "Reserved 0x13", /* 0x13 */ 227 "Reserved 0x14", /* 0x14 */ 228 "Reserved 0x15", /* 0x15 */ 229 "Reserved 0x16", /* 0x16 */ 230 "Reserved 0x17", /* 0x17 */ 231 "Reserved 0x18", /* 0x18 */ 232 "Reserved 0x19", /* 0x19 */ 233 "TSCH Synchronization IE", /* 0x1a */ 234 "TSCH Slotframe and Link IE", /* 0x1b */ 235 "TSCH Timeslot IE", /* 0x1c */ 236 "Hopping timing IE", /* 0x1d */ 237 "Enhanced Beacon Filter IE", /* 0x1e */ 238 "MAC Metrics IE", /* 0x1f */ 239 "All MAC Metrics IE", /* 0x20 */ 240 "Coexistence Specification IE", /* 0x21 */ 241 "SUN Device Capabilities IE", /* 0x22 */ 242 "SUN FSK Generic PHY IE", /* 0x23 */ 243 "Mode Switch Parameter IE", /* 0x24 */ 244 "PHY Parameter Change IE", /* 0x25 */ 245 "O-QPSK PHY Mode IE", /* 0x26 */ 246 "PCA Allocation IE", /* 0x27 */ 247 "LECIM DSSS Operating Mode IE", /* 0x28 */ 248 "LECIM FSK Operating Mode IE", /* 0x29 */ 249 "Reserved 0x2a", /* 0x2a */ 250 "TVWS PHY Operating Mode Description IE", /* 0x2b */ 251 "TVWS Device Capabilities IE", /* 0x2c */ 252 "TVWS Device Category IE", /* 0x2d */ 253 "TVWS Device Identiication IE", /* 0x2e */ 254 "TVWS Device Location IE", /* 0x2f */ 255 "TVWS Channel Information Query IE", /* 0x30 */ 256 "TVWS Channel Information Source IE", /* 0x31 */ 257 "CTM IE", /* 0x32 */ 258 "Timestamp IE", /* 0x33 */ 259 "Timestamp Difference IE", /* 0x34 */ 260 "TMCTP Specification IE", /* 0x35 */ 261 "RCC PHY Operating Mode IE", /* 0x36 */ 262 "Reserved 0x37", /* 0x37 */ 263 "Reserved 0x38", /* 0x38 */ 264 "Reserved 0x39", /* 0x39 */ 265 "Reserved 0x3a", /* 0x3a */ 266 "Reserved 0x3b", /* 0x3b */ 267 "Reserved 0x3c", /* 0x3c */ 268 "Reserved 0x3d", /* 0x3d */ 269 "Reserved 0x3e", /* 0x3e */ 270 "Reserved 0x3f", /* 0x3f */ 271 "Reserved 0x40", /* 0x40 */ 272 "Reserved 0x41", /* 0x41 */ 273 "Reserved 0x42", /* 0x42 */ 274 "Reserved 0x43", /* 0x43 */ 275 "Reserved 0x44", /* 0x44 */ 276 "Reserved 0x45", /* 0x45 */ 277 "Reserved 0x46", /* 0x46 */ 278 "Reserved 0x47", /* 0x47 */ 279 "Reserved 0x48", /* 0x48 */ 280 "Reserved 0x49", /* 0x49 */ 281 "Reserved 0x4a", /* 0x4a */ 282 "Reserved 0x4b", /* 0x4b */ 283 "Reserved 0x4c", /* 0x4c */ 284 "Reserved 0x4d", /* 0x4d */ 285 "Reserved 0x4e", /* 0x4e */ 286 "Reserved 0x4f", /* 0x4f */ 287 "Reserved 0x50", /* 0x50 */ 288 "Reserved 0x51", /* 0x51 */ 289 "Reserved 0x52", /* 0x52 */ 290 "Reserved 0x53", /* 0x53 */ 291 "Reserved 0x54", /* 0x54 */ 292 "Reserved 0x55", /* 0x55 */ 293 "Reserved 0x56", /* 0x56 */ 294 "Reserved 0x57", /* 0x57 */ 295 "Reserved 0x58", /* 0x58 */ 296 "Reserved 0x59", /* 0x59 */ 297 "Reserved 0x5a", /* 0x5a */ 298 "Reserved 0x5b", /* 0x5b */ 299 "Reserved 0x5c", /* 0x5c */ 300 "Reserved 0x5d", /* 0x5d */ 301 "Reserved 0x5e", /* 0x5e */ 302 "Reserved 0x5f", /* 0x5f */ 303 "Reserved 0x60", /* 0x60 */ 304 "Reserved 0x61", /* 0x61 */ 305 "Reserved 0x62", /* 0x62 */ 306 "Reserved 0x63", /* 0x63 */ 307 "Reserved 0x64", /* 0x64 */ 308 "Reserved 0x65", /* 0x65 */ 309 "Reserved 0x66", /* 0x66 */ 310 "Reserved 0x67", /* 0x67 */ 311 "Reserved 0x68", /* 0x68 */ 312 "Reserved 0x69", /* 0x69 */ 313 "Reserved 0x6a", /* 0x6a */ 314 "Reserved 0x6b", /* 0x6b */ 315 "Reserved 0x6c", /* 0x6c */ 316 "Reserved 0x6d", /* 0x6d */ 317 "Reserved 0x6e", /* 0x6e */ 318 "Reserved 0x6f", /* 0x6f */ 319 "Reserved 0x70", /* 0x70 */ 320 "Reserved 0x71", /* 0x71 */ 321 "Reserved 0x72", /* 0x72 */ 322 "Reserved 0x73", /* 0x73 */ 323 "Reserved 0x74", /* 0x74 */ 324 "Reserved 0x75", /* 0x75 */ 325 "Reserved 0x76", /* 0x76 */ 326 "Reserved 0x77", /* 0x77 */ 327 "Reserved 0x78", /* 0x78 */ 328 "Reserved 0x79", /* 0x79 */ 329 "Reserved 0x7a", /* 0x7a */ 330 "Reserved 0x7b", /* 0x7b */ 331 "Reserved 0x7c", /* 0x7c */ 332 "Reserved 0x7d", /* 0x7d */ 333 "Reserved 0x7e", /* 0x7e */ 334 "Reserved 0x7f" /* 0x7f */ 335 }; 336 337 /* Sub-ID for long format from Table 7-17 of 802.15.4-2015 */ 338 static const char *p_mlme_long_names[] = { 339 "Reserved 0x00", /* 0x00 */ 340 "Reserved 0x01", /* 0x01 */ 341 "Reserved 0x02", /* 0x02 */ 342 "Reserved 0x03", /* 0x03 */ 343 "Reserved 0x04", /* 0x04 */ 344 "Reserved 0x05", /* 0x05 */ 345 "Reserved 0x06", /* 0x06 */ 346 "Reserved 0x07", /* 0x07 */ 347 "Vendor Specific MLME Nested IE", /* 0x08 */ 348 "Channel Hopping IE", /* 0x09 */ 349 "Reserved 0x0a", /* 0x0a */ 350 "Reserved 0x0b", /* 0x0b */ 351 "Reserved 0x0c", /* 0x0c */ 352 "Reserved 0x0d", /* 0x0d */ 353 "Reserved 0x0e", /* 0x0e */ 354 "Reserved 0x0f" /* 0x0f */ 355 }; 356 357 /* MAC commands from Table 7-49 of 802.15.4-2015 */ 358 static const char *mac_c_names[] = { 359 "Reserved 0x00", /* 0x00 */ 360 "Association Request command", /* 0x01 */ 361 "Association Response command", /* 0x02 */ 362 "Disassociation Notification command", /* 0x03 */ 363 "Data Request command", /* 0x04 */ 364 "PAN ID Conflict Notification command", /* 0x05 */ 365 "Orphan Notification command", /* 0x06 */ 366 "Beacon Request command", /* 0x07 */ 367 "Coordinator realignment command", /* 0x08 */ 368 "GTS request command", /* 0x09 */ 369 "TRLE Management Request command", /* 0x0a */ 370 "TRLE Management Response command", /* 0x0b */ 371 "Reserved 0x0c", /* 0x0c */ 372 "Reserved 0x0d", /* 0x0d */ 373 "Reserved 0x0e", /* 0x0e */ 374 "Reserved 0x0f", /* 0x0f */ 375 "Reserved 0x10", /* 0x10 */ 376 "Reserved 0x11", /* 0x11 */ 377 "Reserved 0x12", /* 0x12 */ 378 "DSME Association Request command", /* 0x13 */ 379 "DSME Association Response command", /* 0x14 */ 380 "DSME GTS Request command", /* 0x15 */ 381 "DSME GTS Response command", /* 0x16 */ 382 "DSME GTS Notify command", /* 0x17 */ 383 "DSME Information Request command", /* 0x18 */ 384 "DSME Information Response command", /* 0x19 */ 385 "DSME Beacon Allocation Notification command", /* 0x1a */ 386 "DSME Beacon Collision Notification command", /* 0x1b */ 387 "DSME Link Report command", /* 0x1c */ 388 "Reserved 0x1d", /* 0x1d */ 389 "Reserved 0x1e", /* 0x1e */ 390 "Reserved 0x1f", /* 0x1f */ 391 "RIT Data Request command", /* 0x20 */ 392 "DBS Request command", /* 0x21 */ 393 "DBS Response command", /* 0x22 */ 394 "RIT Data Response command", /* 0x23 */ 395 "Vendor Specific command", /* 0x24 */ 396 "Reserved 0x25", /* 0x25 */ 397 "Reserved 0x26", /* 0x26 */ 398 "Reserved 0x27", /* 0x27 */ 399 "Reserved 0x28", /* 0x28 */ 400 "Reserved 0x29", /* 0x29 */ 401 "Reserved 0x2a", /* 0x2a */ 402 "Reserved 0x2b", /* 0x2b */ 403 "Reserved 0x2c", /* 0x2c */ 404 "Reserved 0x2d", /* 0x2d */ 405 "Reserved 0x2e", /* 0x2e */ 406 "Reserved 0x2f" /* 0x2f */ 407 }; 408 409 /* 410 * Frame Control subfields. 411 */ 412 #define FC_FRAME_TYPE(fc) ((fc) & 0x7) 413 #define FC_FRAME_VERSION(fc) (((fc) >> 12) & 0x3) 414 415 #define FC_ADDRESSING_MODE_NONE 0x00 416 #define FC_ADDRESSING_MODE_RESERVED 0x01 417 #define FC_ADDRESSING_MODE_SHORT 0x02 418 #define FC_ADDRESSING_MODE_LONG 0x03 419 420 /* 421 * IEEE 802.15.4 CRC 16 function. This is using CCITT polynomical of 0x1021, 422 * but the initial value is 0, and the bits are reversed for both in and out. 423 * See section 7.2.10 of 802.15.4-2015 for more information. 424 */ 425 static uint16_t 426 ieee802_15_4_crc16(netdissect_options *ndo, const u_char *p, 427 u_int data_len) 428 { 429 uint16_t crc; 430 u_char x, y; 431 432 crc = 0x0000; /* Note, initial value is 0x0000 not 0xffff. */ 433 434 while (data_len != 0){ 435 y = GET_U_1(p); 436 p++; 437 /* Reverse bits on input */ 438 y = (((y & 0xaa) >> 1) | ((y & 0x55) << 1)); 439 y = (((y & 0xcc) >> 2) | ((y & 0x33) << 2)); 440 y = (((y & 0xf0) >> 4) | ((y & 0x0f) << 4)); 441 /* Update CRC */ 442 x = crc >> 8 ^ y; 443 x ^= x >> 4; 444 crc = ((uint16_t)(crc << 8)) ^ 445 ((uint16_t)(x << 12)) ^ 446 ((uint16_t)(x << 5)) ^ 447 ((uint16_t)x); 448 data_len--; 449 } 450 /* Reverse bits on output */ 451 crc = (((crc & 0xaaaa) >> 1) | ((crc & 0x5555) << 1)); 452 crc = (((crc & 0xcccc) >> 2) | ((crc & 0x3333) << 2)); 453 crc = (((crc & 0xf0f0) >> 4) | ((crc & 0x0f0f) << 4)); 454 crc = (((crc & 0xff00) >> 8) | ((crc & 0x00ff) << 8)); 455 return crc; 456 } 457 458 /* 459 * Reverses the bits of the 32-bit word. 460 */ 461 static uint32_t 462 ieee802_15_4_reverse32(uint32_t x) 463 { 464 x = ((x & 0x55555555) << 1) | ((x >> 1) & 0x55555555); 465 x = ((x & 0x33333333) << 2) | ((x >> 2) & 0x33333333); 466 x = ((x & 0x0F0F0F0F) << 4) | ((x >> 4) & 0x0F0F0F0F); 467 x = (x << 24) | ((x & 0xFF00) << 8) | 468 ((x >> 8) & 0xFF00) | (x >> 24); 469 return x; 470 } 471 472 /* 473 * IEEE 802.15.4 CRC 32 function. This is using ANSI X3.66-1979 polynomical of 474 * 0x04C11DB7, but the initial value is 0, and the bits are reversed for both 475 * in and out. See section 7.2.10 of 802.15.4-2015 for more information. 476 */ 477 static uint32_t 478 ieee802_15_4_crc32(netdissect_options *ndo, const u_char *p, 479 u_int data_len) 480 { 481 uint32_t crc, byte; 482 int b; 483 484 crc = 0x00000000; /* Note, initial value is 0x00000000 not 0xffffffff */ 485 486 while (data_len != 0){ 487 byte = GET_U_1(p); 488 p++; 489 /* Reverse bits on input */ 490 byte = ieee802_15_4_reverse32(byte); 491 /* Update CRC */ 492 for(b = 0; b <= 7; b++) { 493 if ((int) (crc ^ byte) < 0) 494 crc = (crc << 1) ^ 0x04C11DB7; 495 else 496 crc = crc << 1; 497 byte = byte << 1; 498 } 499 data_len--; 500 } 501 /* Reverse bits on output */ 502 crc = ieee802_15_4_reverse32(crc); 503 return crc; 504 } 505 506 /* 507 * Find out the address length based on the address type. See table 7-3 of 508 * 802.15.4-2015. Returns the address length. 509 */ 510 static int 511 ieee802_15_4_addr_len(uint16_t addr_type) 512 { 513 switch (addr_type) { 514 case FC_ADDRESSING_MODE_NONE: /* None. */ 515 return 0; 516 break; 517 case FC_ADDRESSING_MODE_RESERVED: /* Reserved, there used to be 8-bit 518 * address type in one amendment, but 519 * that and the feature using it was 520 * removed during 802.15.4-2015 521 * maintenance process. */ 522 return -1; 523 break; 524 case FC_ADDRESSING_MODE_SHORT: /* Short. */ 525 return 2; 526 break; 527 case FC_ADDRESSING_MODE_LONG: /* Extended. */ 528 return 8; 529 break; 530 } 531 return 0; 532 } 533 534 /* 535 * Print out the ieee 802.15.4 address. 536 */ 537 static void 538 ieee802_15_4_print_addr(netdissect_options *ndo, const u_char *p, 539 int dst_addr_len) 540 { 541 switch (dst_addr_len) { 542 case 0: 543 ND_PRINT("none"); 544 break; 545 case 2: 546 ND_PRINT("%04x", GET_LE_U_2(p)); 547 break; 548 case 8: 549 ND_PRINT("%s", GET_LE64ADDR_STRING(p)); 550 break; 551 } 552 } 553 554 /* 555 * Beacon frame superframe specification structure. Used in the old Beacon 556 * frames, and in the DSME PAN Descriptor IE. See section 7.3.1.3 of the 557 * 802.15.4-2015. 558 */ 559 static void 560 ieee802_15_4_print_superframe_specification(netdissect_options *ndo, 561 uint16_t ss) 562 { 563 if (ndo->ndo_vflag < 1) { 564 return; 565 } 566 ND_PRINT("\n\tBeacon order = %d, Superframe order = %d, ", 567 (ss & 0xf), ((ss >> 4) & 0xf)); 568 ND_PRINT("Final CAP Slot = %d", 569 ((ss >> 8) & 0xf)); 570 if (CHECK_BIT(ss, 12)) { ND_PRINT(", BLE enabled"); } 571 if (CHECK_BIT(ss, 14)) { ND_PRINT(", PAN Coordinator"); } 572 if (CHECK_BIT(ss, 15)) { ND_PRINT(", Association Permit"); } 573 } 574 575 /* 576 * Beacon frame gts info structure. Used in the old Beacon frames, and 577 * in the DSME PAN Descriptor IE. See section 7.3.1.4 of 802.15.4-2015. 578 * 579 * Returns number of byts consumed from the packet or -1 in case of error. 580 */ 581 static int 582 ieee802_15_4_print_gts_info(netdissect_options *ndo, 583 const u_char *p, 584 u_int data_len) 585 { 586 uint8_t gts_spec, gts_cnt; 587 u_int len; 588 int i; 589 590 gts_spec = GET_U_1(p); 591 gts_cnt = gts_spec & 0x7; 592 593 if (gts_cnt == 0) { 594 if (ndo->ndo_vflag > 0) { 595 ND_PRINT("\n\tGTS Descriptor Count = %d, ", gts_cnt); 596 } 597 return 1; 598 } 599 len = 1 + 1 + gts_cnt * 3; 600 601 if (data_len < len) { 602 ND_PRINT(" [ERROR: Truncated GTS Info List]"); 603 return -1; 604 } 605 if (ndo->ndo_vflag < 2) { 606 return len; 607 } 608 ND_PRINT("GTS Descriptor Count = %d, ", gts_cnt); 609 ND_PRINT("GTS Directions Mask = %02x, [ ", 610 GET_U_1(p + 1) & 0x7f); 611 612 for(i = 0; i < gts_cnt; i++) { 613 ND_PRINT("[ "); 614 ieee802_15_4_print_addr(ndo, p + 2 + i * 3, 2); 615 ND_PRINT(", Start slot = %d, Length = %d ] ", 616 GET_U_1(p + 2 + i * 3 + 1) & 0x0f, 617 (GET_U_1(p + 2 + i * 3 + 1) >> 4) & 0x0f); 618 } 619 ND_PRINT("]"); 620 return len; 621 } 622 623 /* 624 * Beacon frame pending address structure. Used in the old Beacon frames, and 625 * in the DSME PAN Descriptor IE. See section 7.3.1.5 of 802.15.4-2015. 626 * 627 * Returns number of byts consumed from the packet or -1 in case of error. 628 */ 629 static int16_t 630 ieee802_15_4_print_pending_addresses(netdissect_options *ndo, 631 const u_char *p, 632 u_int data_len) 633 { 634 uint8_t pas, s_cnt, e_cnt, len, i; 635 636 pas = GET_U_1(p); 637 s_cnt = pas & 0x7; 638 e_cnt = (pas >> 4) & 0x7; 639 len = 1 + s_cnt * 2 + e_cnt * 8; 640 if (ndo->ndo_vflag > 0) { 641 ND_PRINT("\n\tPending address list, " 642 "# short addresses = %d, # extended addresses = %d", 643 s_cnt, e_cnt); 644 } 645 if (data_len < len) { 646 ND_PRINT(" [ERROR: Pending address list truncated]"); 647 return -1; 648 } 649 if (ndo->ndo_vflag < 2) { 650 return len; 651 } 652 if (s_cnt != 0) { 653 ND_PRINT(", Short address list = [ "); 654 for(i = 0; i < s_cnt; i++) { 655 ieee802_15_4_print_addr(ndo, p + 1 + i * 2, 2); 656 ND_PRINT(" "); 657 } 658 ND_PRINT("]"); 659 } 660 if (e_cnt != 0) { 661 ND_PRINT(", Extended address list = [ "); 662 for(i = 0; i < e_cnt; i++) { 663 ieee802_15_4_print_addr(ndo, p + 1 + s_cnt * 2 + 664 i * 8, 8); 665 ND_PRINT(" "); 666 } 667 ND_PRINT("]"); 668 } 669 return len; 670 } 671 672 /* 673 * Print header ie content. 674 */ 675 static void 676 ieee802_15_4_print_header_ie(netdissect_options *ndo, 677 const u_char *p, 678 uint16_t ie_len, 679 int element_id) 680 { 681 int i; 682 683 switch (element_id) { 684 case 0x00: /* Vendor Specific Header IE */ 685 if (ie_len < 3) { 686 ND_PRINT("[ERROR: Vendor OUI missing]"); 687 } else { 688 ND_PRINT("OUI = 0x%02x%02x%02x, ", GET_U_1(p), 689 GET_U_1(p + 1), GET_U_1(p + 2)); 690 ND_PRINT("Data = "); 691 for(i = 3; i < ie_len; i++) { 692 ND_PRINT("%02x ", GET_U_1(p + i)); 693 } 694 } 695 break; 696 case 0x1a: /* LE CSL IE */ 697 if (ie_len < 4) { 698 ND_PRINT("[ERROR: Truncated CSL IE]"); 699 } else { 700 ND_PRINT("CSL Phase = %d, CSL Period = %d", 701 GET_LE_U_2(p), GET_LE_U_2(p + 2)); 702 if (ie_len >= 6) { 703 ND_PRINT(", Rendezvous time = %d", 704 GET_LE_U_2(p + 4)); 705 } 706 if (ie_len != 4 && ie_len != 6) { 707 ND_PRINT(" [ERROR: CSL IE length wrong]"); 708 } 709 } 710 break; 711 case 0x1b: /* LE RIT IE */ 712 if (ie_len < 4) { 713 ND_PRINT("[ERROR: Truncated RIT IE]"); 714 } else { 715 ND_PRINT("Time to First Listen = %d, # of Repeat Listen = %d, Repeat Listen Interval = %d", 716 GET_U_1(p), 717 GET_U_1(p + 1), 718 GET_LE_U_2(p + 2)); 719 } 720 break; 721 case 0x1c: /* DSME PAN Descriptor IE */ 722 /*FALLTHROUGH*/ 723 case 0x21: /* Extended DSME PAN descriptor IE */ 724 if (ie_len < 2) { 725 ND_PRINT("[ERROR: Truncated DSME PAN IE]"); 726 } else { 727 uint16_t ss, ptr, ulen; 728 int16_t len; 729 int hopping_present; 730 731 hopping_present = 0; 732 733 ss = GET_LE_U_2(p); 734 ieee802_15_4_print_superframe_specification(ndo, ss); 735 if (ie_len < 3) { 736 ND_PRINT("[ERROR: Truncated before pending addresses field]"); 737 break; 738 } 739 ptr = 2; 740 len = ieee802_15_4_print_pending_addresses(ndo, 741 p + ptr, 742 ie_len - 743 ptr); 744 if (len < 0) { 745 break; 746 } 747 ptr += len; 748 749 if (element_id == 0x21) { 750 /* Extended version. */ 751 if (ie_len < ptr + 2) { 752 ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]"); 753 break; 754 } 755 ss = GET_LE_U_2(p + ptr); 756 ptr += 2; 757 ND_PRINT("Multi-superframe Order = %d", ss & 0xff); 758 ND_PRINT(", %s", ((ss & 0x100) ? 759 "Channel hopping mode" : 760 "Channel adaptation mode")); 761 if (ss & 0x400) { 762 ND_PRINT(", CAP reduction enabled"); 763 } 764 if (ss & 0x800) { 765 ND_PRINT(", Deferred beacon enabled"); 766 } 767 if (ss & 0x1000) { 768 ND_PRINT(", Hopping Sequence Present"); 769 hopping_present = 1; 770 } 771 } else { 772 if (ie_len < ptr + 1) { 773 ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]"); 774 break; 775 } 776 ss = GET_U_1(p + ptr); 777 ptr++; 778 ND_PRINT("Multi-superframe Order = %d", 779 ss & 0x0f); 780 ND_PRINT(", %s", ((ss & 0x10) ? 781 "Channel hopping mode" : 782 "Channel adaptation mode")); 783 if (ss & 0x40) { 784 ND_PRINT(", CAP reduction enabled"); 785 } 786 if (ss & 0x80) { 787 ND_PRINT(", Deferred beacon enabled"); 788 } 789 } 790 if (ie_len < ptr + 8) { 791 ND_PRINT(" [ERROR: Truncated before Time synchronization specification]"); 792 break; 793 } 794 ND_PRINT("Beacon timestamp = %" PRIu64 ", offset = %d", 795 GET_LE_U_6(p + ptr), 796 GET_LE_U_2(p + ptr + 6)); 797 ptr += 8; 798 if (ie_len < ptr + 4) { 799 ND_PRINT(" [ERROR: Truncated before Beacon Bitmap]"); 800 break; 801 } 802 803 ulen = GET_LE_U_2(p + ptr + 2); 804 ND_PRINT("SD Index = %d, Bitmap len = %d, ", 805 GET_LE_U_2(p + ptr), ulen); 806 ptr += 4; 807 if (ie_len < ptr + ulen) { 808 ND_PRINT(" [ERROR: Truncated in SD bitmap]"); 809 break; 810 } 811 ND_PRINT(" SD Bitmap = "); 812 for(i = 0; i < ulen; i++) { 813 ND_PRINT("%02x ", GET_U_1(p + ptr + i)); 814 } 815 ptr += ulen; 816 817 if (ie_len < ptr + 5) { 818 ND_PRINT(" [ERROR: Truncated before Channel hopping specification]"); 819 break; 820 } 821 822 ulen = GET_LE_U_2(p + ptr + 4); 823 ND_PRINT("Hopping Seq ID = %d, PAN Coordinator BSN = %d, " 824 "Channel offset = %d, Bitmap length = %d, ", 825 GET_U_1(p + ptr), 826 GET_U_1(p + ptr + 1), 827 GET_LE_U_2(p + ptr + 2), 828 ulen); 829 ptr += 5; 830 if (ie_len < ptr + ulen) { 831 ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]"); 832 break; 833 } 834 ND_PRINT(" Channel offset bitmap = "); 835 for(i = 0; i < ulen; i++) { 836 ND_PRINT("%02x ", GET_U_1(p + ptr + i)); 837 } 838 ptr += ulen; 839 if (hopping_present) { 840 if (ie_len < ptr + 1) { 841 ND_PRINT(" [ERROR: Truncated in Hopping Sequence length]"); 842 break; 843 } 844 ulen = GET_U_1(p + ptr); 845 ptr++; 846 ND_PRINT("Hopping Seq length = %d [ ", ulen); 847 848 /* The specification is not clear how the 849 hopping sequence is encoded, I assume two 850 octet unsigned integers for each channel. */ 851 852 if (ie_len < ptr + ulen * 2) { 853 ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]"); 854 break; 855 } 856 for(i = 0; i < ulen; i++) { 857 ND_PRINT("%02x ", 858 GET_LE_U_2(p + ptr + i * 2)); 859 } 860 ND_PRINT("]"); 861 ptr += ulen * 2; 862 } 863 } 864 break; 865 case 0x1d: /* Rendezvous Tome IE */ 866 if (ie_len != 4) { 867 ND_PRINT("[ERROR: Length != 2]"); 868 } else { 869 uint16_t r_time, w_u_interval; 870 r_time = GET_LE_U_2(p); 871 w_u_interval = GET_LE_U_2(p + 2); 872 873 ND_PRINT("Rendezvous time = %d, Wake-up Interval = %d", 874 r_time, w_u_interval); 875 } 876 break; 877 case 0x1e: /* Time correction IE */ 878 if (ie_len != 2) { 879 ND_PRINT("[ERROR: Length != 2]"); 880 } else { 881 uint16_t val; 882 int16_t timecorr; 883 884 val = GET_LE_U_2(p); 885 if (val & 0x8000) { ND_PRINT("Negative "); } 886 val &= 0xfff; 887 val <<= 4; 888 timecorr = val; 889 timecorr >>= 4; 890 891 ND_PRINT("Ack time correction = %d, ", timecorr); 892 } 893 break; 894 case 0x22: /* Fragment Sequence Content Description IE */ 895 /* XXX Not implemented */ 896 case 0x23: /* Simplified Superframe Specification IE */ 897 /* XXX Not implemented */ 898 case 0x24: /* Simplified GTS Specification IE */ 899 /* XXX Not implemented */ 900 case 0x25: /* LECIM Capabilities IE */ 901 /* XXX Not implemented */ 902 case 0x26: /* TRLE Descriptor IE */ 903 /* XXX Not implemented */ 904 case 0x27: /* RCC Capabilities IE */ 905 /* XXX Not implemented */ 906 case 0x28: /* RCCN Descriptor IE */ 907 /* XXX Not implemented */ 908 case 0x29: /* Global Time IE */ 909 /* XXX Not implemented */ 910 case 0x2b: /* DA IE */ 911 /* XXX Not implemented */ 912 default: 913 ND_PRINT("IE Data = "); 914 for(i = 0; i < ie_len; i++) { 915 ND_PRINT("%02x ", GET_U_1(p + i)); 916 } 917 break; 918 } 919 } 920 921 /* 922 * Parse and print Header IE list. See 7.4.2 of 802.15.4-2015 for 923 * more information. 924 * 925 * Returns number of byts consumed from the packet or -1 in case of error. 926 */ 927 static int 928 ieee802_15_4_print_header_ie_list(netdissect_options *ndo, 929 const u_char *p, 930 u_int caplen, 931 int *payload_ie_present) 932 { 933 int len, ie, element_id, i; 934 uint16_t ie_len; 935 936 *payload_ie_present = 0; 937 len = 0; 938 do { 939 if (caplen < 2) { 940 ND_PRINT("[ERROR: Truncated header IE]"); 941 return -1; 942 } 943 /* Extract IE Header */ 944 ie = GET_LE_U_2(p); 945 if (CHECK_BIT(ie, 15)) { 946 ND_PRINT("[ERROR: Header IE with type 1] "); 947 } 948 /* Get length and Element ID */ 949 ie_len = ie & 0x7f; 950 element_id = (ie >> 7) & 0xff; 951 if (element_id > 127) { 952 ND_PRINT("Reserved Element ID %02x, length = %d ", 953 element_id, ie_len); 954 } else { 955 if (ie_len == 0) { 956 ND_PRINT("\n\t%s [", h_ie_names[element_id]); 957 } else { 958 ND_PRINT("\n\t%s [ length = %d, ", 959 h_ie_names[element_id], ie_len); 960 } 961 } 962 if (caplen < 2U + ie_len) { 963 ND_PRINT("[ERROR: Truncated IE data]"); 964 return -1; 965 } 966 /* Skip header */ 967 p += 2; 968 969 /* Parse and print content. */ 970 if (ndo->ndo_vflag > 3 && ie_len != 0) { 971 ieee802_15_4_print_header_ie(ndo, p, 972 ie_len, element_id); 973 } else { 974 if (ie_len != 0) { 975 ND_PRINT("IE Data = "); 976 for(i = 0; i < ie_len; i++) { 977 ND_PRINT("%02x ", GET_U_1(p + i)); 978 } 979 } 980 } 981 ND_PRINT("] "); 982 len += 2 + ie_len; 983 p += ie_len; 984 caplen -= 2 + ie_len; 985 if (element_id == 0x7e) { 986 *payload_ie_present = 1; 987 break; 988 } 989 if (element_id == 0x7f) { 990 break; 991 } 992 } while (caplen != 0); 993 return len; 994 } 995 996 /* 997 * Print MLME ie content. 998 */ 999 static void 1000 ieee802_15_4_print_mlme_ie(netdissect_options *ndo, 1001 const u_char *p, 1002 uint16_t sub_ie_len, 1003 int sub_id) 1004 { 1005 int i, j; 1006 uint16_t len; 1007 1008 /* Note, as there is no overlap with the long and short 1009 MLME sub IDs, we can just use one switch here. */ 1010 switch (sub_id) { 1011 case 0x08: /* Vendor Specific Nested IE */ 1012 if (sub_ie_len < 3) { 1013 ND_PRINT("[ERROR: Vendor OUI missing]"); 1014 } else { 1015 ND_PRINT("OUI = 0x%02x%02x%02x, ", 1016 GET_U_1(p), 1017 GET_U_1(p + 1), 1018 GET_U_1(p + 2)); 1019 ND_PRINT("Data = "); 1020 for(i = 3; i < sub_ie_len; i++) { 1021 ND_PRINT("%02x ", GET_U_1(p + i)); 1022 } 1023 } 1024 break; 1025 case 0x09: /* Channel Hopping IE */ 1026 if (sub_ie_len < 1) { 1027 ND_PRINT("[ERROR: Hopping sequence ID missing]"); 1028 } else if (sub_ie_len == 1) { 1029 ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p)); 1030 p++; 1031 sub_ie_len--; 1032 } else { 1033 uint16_t channel_page, number_of_channels; 1034 1035 ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p)); 1036 p++; 1037 sub_ie_len--; 1038 if (sub_ie_len < 7) { 1039 ND_PRINT("[ERROR: IE truncated]"); 1040 break; 1041 } 1042 channel_page = GET_U_1(p); 1043 number_of_channels = GET_LE_U_2(p + 1); 1044 ND_PRINT("Channel Page = %d, Number of Channels = %d, ", 1045 channel_page, number_of_channels); 1046 ND_PRINT("Phy Configuration = 0x%08x, ", 1047 GET_LE_U_4(p + 3)); 1048 p += 7; 1049 sub_ie_len -= 7; 1050 if (channel_page == 9 || channel_page == 10) { 1051 len = (number_of_channels + 7) / 8; 1052 if (sub_ie_len < len) { 1053 ND_PRINT("[ERROR: IE truncated]"); 1054 break; 1055 } 1056 ND_PRINT("Extended bitmap = 0x"); 1057 for(i = 0; i < len; i++) { 1058 ND_PRINT("%02x", GET_U_1(p + i)); 1059 } 1060 ND_PRINT(", "); 1061 p += len; 1062 sub_ie_len -= len; 1063 } 1064 if (sub_ie_len < 2) { 1065 ND_PRINT("[ERROR: IE truncated]"); 1066 break; 1067 } 1068 len = GET_LE_U_2(p); 1069 p += 2; 1070 sub_ie_len -= 2; 1071 ND_PRINT("Hopping Seq length = %d [ ", len); 1072 1073 if (sub_ie_len < len * 2) { 1074 ND_PRINT(" [ERROR: IE truncated]"); 1075 break; 1076 } 1077 for(i = 0; i < len; i++) { 1078 ND_PRINT("%02x ", GET_LE_U_2(p + i * 2)); 1079 } 1080 ND_PRINT("]"); 1081 p += len * 2; 1082 sub_ie_len -= len * 2; 1083 if (sub_ie_len < 2) { 1084 ND_PRINT("[ERROR: IE truncated]"); 1085 break; 1086 } 1087 ND_PRINT("Current hop = %d", GET_LE_U_2(p)); 1088 } 1089 1090 break; 1091 case 0x1a: /* TSCH Synchronization IE. */ 1092 if (sub_ie_len < 6) { 1093 ND_PRINT("[ERROR: Length != 6]"); 1094 } 1095 ND_PRINT("ASN = %010" PRIx64 ", Join Metric = %d ", 1096 GET_LE_U_5(p), GET_U_1(p + 5)); 1097 break; 1098 case 0x1b: /* TSCH Slotframe and Link IE. */ 1099 { 1100 int sf_num, off, links, opts; 1101 1102 if (sub_ie_len < 1) { 1103 ND_PRINT("[ERROR: Truncated IE]"); 1104 break; 1105 } 1106 sf_num = GET_U_1(p); 1107 ND_PRINT("Slotframes = %d ", sf_num); 1108 off = 1; 1109 for(i = 0; i < sf_num; i++) { 1110 if (sub_ie_len < off + 4) { 1111 ND_PRINT("[ERROR: Truncated IE before slotframes]"); 1112 break; 1113 } 1114 links = GET_U_1(p + off + 3); 1115 ND_PRINT("\n\t\t\t[ Handle %d, size = %d, links = %d ", 1116 GET_U_1(p + off), 1117 GET_LE_U_2(p + off + 1), 1118 links); 1119 off += 4; 1120 for(j = 0; j < links; j++) { 1121 if (sub_ie_len < off + 5) { 1122 ND_PRINT("[ERROR: Truncated IE links]"); 1123 break; 1124 } 1125 opts = GET_U_1(p + off + 4); 1126 ND_PRINT("\n\t\t\t\t[ Timeslot = %d, Offset = %d, Options = ", 1127 GET_LE_U_2(p + off), 1128 GET_LE_U_2(p + off + 2)); 1129 if (opts & 0x1) { ND_PRINT("TX "); } 1130 if (opts & 0x2) { ND_PRINT("RX "); } 1131 if (opts & 0x4) { ND_PRINT("Shared "); } 1132 if (opts & 0x8) { 1133 ND_PRINT("Timekeeping "); 1134 } 1135 if (opts & 0x10) { 1136 ND_PRINT("Priority "); 1137 } 1138 off += 5; 1139 ND_PRINT("] "); 1140 } 1141 ND_PRINT("] "); 1142 } 1143 } 1144 break; 1145 case 0x1c: /* TSCH Timeslot IE. */ 1146 if (sub_ie_len == 1) { 1147 ND_PRINT("Time slot ID = %d ", GET_U_1(p)); 1148 } else if (sub_ie_len == 25) { 1149 ND_PRINT("Time slot ID = %d, CCA Offset = %d, CCA = %d, TX Offset = %d, RX Offset = %d, RX Ack Delay = %d, TX Ack Delay = %d, RX Wait = %d, Ack Wait = %d, RX TX = %d, Max Ack = %d, Max TX = %d, Time slot Length = %d ", 1150 GET_U_1(p), 1151 GET_LE_U_2(p + 1), 1152 GET_LE_U_2(p + 3), 1153 GET_LE_U_2(p + 5), 1154 GET_LE_U_2(p + 7), 1155 GET_LE_U_2(p + 9), 1156 GET_LE_U_2(p + 11), 1157 GET_LE_U_2(p + 13), 1158 GET_LE_U_2(p + 15), 1159 GET_LE_U_2(p + 17), 1160 GET_LE_U_2(p + 19), 1161 GET_LE_U_2(p + 21), 1162 GET_LE_U_2(p + 23)); 1163 } else if (sub_ie_len == 27) { 1164 ND_PRINT("Time slot ID = %d, CCA Offset = %d, CCA = %d, TX Offset = %d, RX Offset = %d, RX Ack Delay = %d, TX Ack Delay = %d, RX Wait = %d, Ack Wait = %d, RX TX = %d, Max Ack = %d, Max TX = %d, Time slot Length = %d ", 1165 GET_U_1(p), 1166 GET_LE_U_2(p + 1), 1167 GET_LE_U_2(p + 3), 1168 GET_LE_U_2(p + 5), 1169 GET_LE_U_2(p + 7), 1170 GET_LE_U_2(p + 9), 1171 GET_LE_U_2(p + 11), 1172 GET_LE_U_2(p + 13), 1173 GET_LE_U_2(p + 15), 1174 GET_LE_U_2(p + 17), 1175 GET_LE_U_2(p + 19), 1176 GET_LE_U_3(p + 21), 1177 GET_LE_U_3(p + 24)); 1178 } else { 1179 ND_PRINT("[ERROR: Length not 1, 25, or 27]"); 1180 ND_PRINT("\n\t\t\tIE Data = "); 1181 for(i = 0; i < sub_ie_len; i++) { 1182 ND_PRINT("%02x ", GET_U_1(p + i)); 1183 } 1184 } 1185 break; 1186 case 0x1d: /* Hopping timing IE */ 1187 /* XXX Not implemented */ 1188 case 0x1e: /* Enhanced Beacon Filter IE */ 1189 /* XXX Not implemented */ 1190 case 0x1f: /* MAC Metrics IE */ 1191 /* XXX Not implemented */ 1192 case 0x20: /* All MAC Metrics IE */ 1193 /* XXX Not implemented */ 1194 case 0x21: /* Coexistence Specification IE */ 1195 /* XXX Not implemented */ 1196 case 0x22: /* SUN Device Capabilities IE */ 1197 /* XXX Not implemented */ 1198 case 0x23: /* SUN FSK Generic PHY IE */ 1199 /* XXX Not implemented */ 1200 case 0x24: /* Mode Switch Parameter IE */ 1201 /* XXX Not implemented */ 1202 case 0x25: /* PHY Parameter Change IE */ 1203 /* XXX Not implemented */ 1204 case 0x26: /* O-QPSK PHY Mode IE */ 1205 /* XXX Not implemented */ 1206 case 0x27: /* PCA Allocation IE */ 1207 /* XXX Not implemented */ 1208 case 0x28: /* LECIM DSSS Operating Mode IE */ 1209 /* XXX Not implemented */ 1210 case 0x29: /* LECIM FSK Operating Mode IE */ 1211 /* XXX Not implemented */ 1212 case 0x2b: /* TVWS PHY Operating Mode Description IE */ 1213 /* XXX Not implemented */ 1214 case 0x2c: /* TVWS Device Capabilities IE */ 1215 /* XXX Not implemented */ 1216 case 0x2d: /* TVWS Device Category IE */ 1217 /* XXX Not implemented */ 1218 case 0x2e: /* TVWS Device Identification IE */ 1219 /* XXX Not implemented */ 1220 case 0x2f: /* TVWS Device Location IE */ 1221 /* XXX Not implemented */ 1222 case 0x30: /* TVWS Channel Information Query IE */ 1223 /* XXX Not implemented */ 1224 case 0x31: /* TVWS Channel Information Source IE */ 1225 /* XXX Not implemented */ 1226 case 0x32: /* CTM IE */ 1227 /* XXX Not implemented */ 1228 case 0x33: /* Timestamp IE */ 1229 /* XXX Not implemented */ 1230 case 0x34: /* Timestamp Difference IE */ 1231 /* XXX Not implemented */ 1232 case 0x35: /* TMCTP Specification IE */ 1233 /* XXX Not implemented */ 1234 case 0x36: /* TCC PHY Operating Mode IE */ 1235 /* XXX Not implemented */ 1236 default: 1237 ND_PRINT("IE Data = "); 1238 for(i = 0; i < sub_ie_len; i++) { 1239 ND_PRINT("%02x ", GET_U_1(p + i)); 1240 } 1241 break; 1242 } 1243 } 1244 1245 /* 1246 * MLME IE list parsing and printing. See 7.4.3.2 of 802.15.4-2015 1247 * for more information. 1248 */ 1249 static void 1250 ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo, 1251 const u_char *p, 1252 uint16_t ie_len) 1253 { 1254 int ie, sub_id, i, type; 1255 uint16_t sub_ie_len; 1256 1257 do { 1258 if (ie_len < 2) { 1259 ND_PRINT("[ERROR: Truncated MLME IE]"); 1260 return; 1261 } 1262 /* Extract IE header */ 1263 ie = GET_LE_U_2(p); 1264 type = CHECK_BIT(ie, 15); 1265 if (type) { 1266 /* Long type */ 1267 sub_ie_len = ie & 0x3ff; 1268 sub_id = (ie >> 11) & 0x0f; 1269 } else { 1270 sub_ie_len = ie & 0xff; 1271 sub_id = (ie >> 8) & 0x7f; 1272 } 1273 1274 /* Skip the IE header */ 1275 p += 2; 1276 1277 if (type == 0) { 1278 ND_PRINT("\n\t\t%s [ length = %d, ", 1279 p_mlme_short_names[sub_id], sub_ie_len); 1280 } else { 1281 ND_PRINT("\n\t\t%s [ length = %d, ", 1282 p_mlme_long_names[sub_id], sub_ie_len); 1283 } 1284 1285 if (ie_len < 2 + sub_ie_len) { 1286 ND_PRINT("[ERROR: Truncated IE data]"); 1287 return; 1288 } 1289 if (sub_ie_len != 0) { 1290 if (ndo->ndo_vflag > 3) { 1291 ieee802_15_4_print_mlme_ie(ndo, p, sub_ie_len, sub_id); 1292 } else if (ndo->ndo_vflag > 2) { 1293 ND_PRINT("IE Data = "); 1294 for(i = 0; i < sub_ie_len; i++) { 1295 ND_PRINT("%02x ", GET_U_1(p + i)); 1296 } 1297 } 1298 } 1299 ND_PRINT("] "); 1300 p += sub_ie_len; 1301 ie_len -= 2 + sub_ie_len; 1302 } while (ie_len > 0); 1303 } 1304 1305 /* 1306 * Multiplexd IE (802.15.9) parsing and printing. 1307 * 1308 * Returns number of bytes consumed from packet or -1 in case of error. 1309 */ 1310 static void 1311 ieee802_15_4_print_mpx_ie(netdissect_options *ndo, 1312 const u_char *p, 1313 uint16_t ie_len) 1314 { 1315 int transfer_type, tid; 1316 int fragment_number, data_start; 1317 int i; 1318 1319 data_start = 0; 1320 if (ie_len < 1) { 1321 ND_PRINT("[ERROR: Transaction control byte missing]"); 1322 return; 1323 } 1324 1325 transfer_type = GET_U_1(p) & 0x7; 1326 tid = GET_U_1(p) >> 3; 1327 switch (transfer_type) { 1328 case 0x00: /* Full upper layer frame. */ 1329 case 0x01: /* Full upper layer frame with small Multiplex ID. */ 1330 ND_PRINT("Type = Full upper layer fragment%s, ", 1331 (transfer_type == 0x01 ? 1332 " with small Multiplex ID" : "")); 1333 if (transfer_type == 0x00) { 1334 if (ie_len < 3) { 1335 ND_PRINT("[ERROR: Multiplex ID missing]"); 1336 return; 1337 } 1338 data_start = 3; 1339 ND_PRINT("tid = 0x%02x, Multiplex ID = 0x%04x, ", 1340 tid, GET_LE_U_2(p + 1)); 1341 } else { 1342 data_start = 1; 1343 ND_PRINT("Multiplex ID = 0x%04x, ", tid); 1344 } 1345 break; 1346 case 0x02: /* First, or middle, Fragments */ 1347 case 0x04: /* Last fragment */ 1348 if (ie_len < 2) { 1349 ND_PRINT("[ERROR: fragment number missing]"); 1350 return; 1351 } 1352 1353 fragment_number = GET_U_1(p + 1); 1354 ND_PRINT("Type = %s, tid = 0x%02x, fragment = 0x%02x, ", 1355 (transfer_type == 0x02 ? 1356 (fragment_number == 0 ? 1357 "First fragment" : "Middle fragment") : 1358 "Last fragment"), tid, 1359 fragment_number); 1360 data_start = 2; 1361 if (fragment_number == 0) { 1362 int total_size, multiplex_id; 1363 1364 if (ie_len < 6) { 1365 ND_PRINT("[ERROR: Total upper layer size or multiplex ID missing]"); 1366 return; 1367 } 1368 total_size = GET_LE_U_2(p + 2); 1369 multiplex_id = GET_LE_U_2(p + 4); 1370 ND_PRINT("Total upper layer size = 0x%04x, Multiplex ID = 0x%04x, ", 1371 total_size, multiplex_id); 1372 data_start = 6; 1373 } 1374 break; 1375 case 0x06: /* Abort code */ 1376 if (ie_len == 1) { 1377 ND_PRINT("Type = Abort, tid = 0x%02x, no max size given", 1378 tid); 1379 } else if (ie_len == 3) { 1380 ND_PRINT("Type = Abort, tid = 0x%02x, max size = 0x%04x", 1381 tid, GET_LE_U_2(p + 1)); 1382 } else { 1383 ND_PRINT("Type = Abort, tid = 0x%02x, invalid length = %d (not 1 or 3)", 1384 tid, ie_len); 1385 ND_PRINT("Abort data = "); 1386 for(i = 1; i < ie_len; i++) { 1387 ND_PRINT("%02x ", GET_U_1(p + i)); 1388 } 1389 } 1390 return; 1391 /* NOTREACHED */ 1392 break; 1393 case 0x03: /* Reserved */ 1394 case 0x05: /* Reserved */ 1395 case 0x07: /* Reserved */ 1396 ND_PRINT("Type = %d (Reserved), tid = 0x%02x, ", 1397 transfer_type, tid); 1398 data_start = 1; 1399 break; 1400 } 1401 1402 ND_PRINT("Upper layer data = "); 1403 for(i = data_start; i < ie_len; i++) { 1404 ND_PRINT("%02x ", GET_U_1(p + i)); 1405 } 1406 } 1407 1408 /* 1409 * Payload IE list parsing and printing. See 7.4.3 of 802.15.4-2015 1410 * for more information. 1411 * 1412 * Returns number of byts consumed from the packet or -1 in case of error. 1413 */ 1414 static int 1415 ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, 1416 const u_char *p, 1417 u_int caplen) 1418 { 1419 int len, ie, group_id, i; 1420 uint16_t ie_len; 1421 1422 len = 0; 1423 do { 1424 if (caplen < 2) { 1425 ND_PRINT("[ERROR: Truncated header IE]"); 1426 return -1; 1427 } 1428 /* Extract IE header */ 1429 ie = GET_LE_U_2(p); 1430 if ((CHECK_BIT(ie, 15)) == 0) { 1431 ND_PRINT("[ERROR: Payload IE with type 0] "); 1432 } 1433 ie_len = ie & 0x3ff; 1434 group_id = (ie >> 11) & 0x0f; 1435 1436 /* Skip the IE header */ 1437 p += 2; 1438 if (ie_len == 0) { 1439 ND_PRINT("\n\t%s [", p_ie_names[group_id]); 1440 } else { 1441 ND_PRINT("\n\t%s [ length = %d, ", 1442 p_ie_names[group_id], ie_len); 1443 } 1444 if (caplen < 2U + ie_len) { 1445 ND_PRINT("[ERROR: Truncated IE data]"); 1446 return -1; 1447 } 1448 if (ndo->ndo_vflag > 3 && ie_len != 0) { 1449 switch (group_id) { 1450 case 0x1: /* MLME IE */ 1451 ieee802_15_4_print_mlme_ie_list(ndo, p, ie_len); 1452 break; 1453 case 0x2: /* Vendor Specific Nested IE */ 1454 if (ie_len < 3) { 1455 ND_PRINT("[ERROR: Vendor OUI missing]"); 1456 } else { 1457 ND_PRINT("OUI = 0x%02x%02x%02x, ", 1458 GET_U_1(p), 1459 GET_U_1(p + 1), 1460 GET_U_1(p + 2)); 1461 ND_PRINT("Data = "); 1462 for(i = 3; i < ie_len; i++) { 1463 ND_PRINT("%02x ", 1464 GET_U_1(p + i)); 1465 } 1466 } 1467 break; 1468 case 0x3: /* Multiplexed IE (802.15.9) */ 1469 ieee802_15_4_print_mpx_ie(ndo, p, ie_len); 1470 break; 1471 case 0x5: /* IETF IE */ 1472 if (ie_len < 1) { 1473 ND_PRINT("[ERROR: Subtype ID missing]"); 1474 } else { 1475 ND_PRINT("Subtype ID = 0x%02x, Subtype content = ", 1476 GET_U_1(p)); 1477 for(i = 1; i < ie_len; i++) { 1478 ND_PRINT("%02x ", 1479 GET_U_1(p + i)); 1480 } 1481 } 1482 break; 1483 default: 1484 ND_PRINT("IE Data = "); 1485 for(i = 0; i < ie_len; i++) { 1486 ND_PRINT("%02x ", GET_U_1(p + i)); 1487 } 1488 break; 1489 } 1490 } else { 1491 if (ie_len != 0) { 1492 ND_PRINT("IE Data = "); 1493 for(i = 0; i < ie_len; i++) { 1494 ND_PRINT("%02x ", GET_U_1(p + i)); 1495 } 1496 } 1497 } 1498 ND_PRINT("]\n\t"); 1499 len += 2 + ie_len; 1500 p += ie_len; 1501 caplen -= 2 + ie_len; 1502 if (group_id == 0xf) { 1503 break; 1504 } 1505 } while (caplen > 0); 1506 return len; 1507 } 1508 1509 /* 1510 * Parse and print auxiliary security header. 1511 * 1512 * Returns number of byts consumed from the packet or -1 in case of error. 1513 */ 1514 static int 1515 ieee802_15_4_print_aux_sec_header(netdissect_options *ndo, 1516 const u_char *p, 1517 u_int caplen, 1518 int *security_level) 1519 { 1520 int sc, key_id_mode, len; 1521 1522 if (caplen < 1) { 1523 ND_PRINT("[ERROR: Truncated before Aux Security Header]"); 1524 return -1; 1525 } 1526 sc = GET_U_1(p); 1527 len = 1; 1528 *security_level = sc & 0x7; 1529 key_id_mode = (sc >> 3) & 0x3; 1530 1531 caplen -= 1; 1532 p += 1; 1533 1534 if (ndo->ndo_vflag > 0) { 1535 ND_PRINT("\n\tSecurity Level %d, Key Id Mode %d, ", 1536 *security_level, key_id_mode); 1537 } 1538 if ((CHECK_BIT(sc, 5)) == 0) { 1539 if (caplen < 4) { 1540 ND_PRINT("[ERROR: Truncated before Frame Counter]"); 1541 return -1; 1542 } 1543 if (ndo->ndo_vflag > 1) { 1544 ND_PRINT("Frame Counter 0x%08x ", 1545 GET_LE_U_4(p)); 1546 } 1547 p += 4; 1548 caplen -= 4; 1549 len += 4; 1550 } 1551 switch (key_id_mode) { 1552 case 0x00: /* Implicit. */ 1553 if (ndo->ndo_vflag > 1) { 1554 ND_PRINT("Implicit"); 1555 } 1556 return len; 1557 break; 1558 case 0x01: /* Key Index, nothing to print here. */ 1559 break; 1560 case 0x02: /* PAN and Short address Key Source, and Key Index. */ 1561 if (caplen < 4) { 1562 ND_PRINT("[ERROR: Truncated before Key Source]"); 1563 return -1; 1564 } 1565 if (ndo->ndo_vflag > 1) { 1566 ND_PRINT("KeySource 0x%04x:%0x4x, ", 1567 GET_LE_U_2(p), GET_LE_U_2(p + 2)); 1568 } 1569 p += 4; 1570 caplen -= 4; 1571 len += 4; 1572 break; 1573 case 0x03: /* Extended address and Key Index. */ 1574 if (caplen < 8) { 1575 ND_PRINT("[ERROR: Truncated before Key Source]"); 1576 return -1; 1577 } 1578 if (ndo->ndo_vflag > 1) { 1579 ND_PRINT("KeySource %s, ", GET_LE64ADDR_STRING(p)); 1580 } 1581 p += 4; 1582 caplen -= 4; 1583 len += 4; 1584 break; 1585 } 1586 if (caplen < 1) { 1587 ND_PRINT("[ERROR: Truncated before Key Index]"); 1588 return -1; 1589 } 1590 if (ndo->ndo_vflag > 1) { 1591 ND_PRINT("KeyIndex 0x%02x, ", GET_U_1(p)); 1592 } 1593 caplen -= 1; 1594 p += 1; 1595 len += 1; 1596 return len; 1597 } 1598 1599 /* 1600 * Print command data. 1601 * 1602 * Returns number of byts consumed from the packet or -1 in case of error. 1603 */ 1604 static int 1605 ieee802_15_4_print_command_data(netdissect_options *ndo, 1606 uint8_t command_id, 1607 const u_char *p, 1608 u_int caplen) 1609 { 1610 u_int i; 1611 1612 switch (command_id) { 1613 case 0x01: /* Association Request */ 1614 if (caplen != 1) { 1615 ND_PRINT("Invalid Association request command length"); 1616 return -1; 1617 } else { 1618 uint8_t cap_info; 1619 cap_info = GET_U_1(p); 1620 ND_PRINT("%s%s%s%s%s%s", 1621 ((cap_info & 0x02) ? 1622 "FFD, " : "RFD, "), 1623 ((cap_info & 0x04) ? 1624 "AC powered, " : ""), 1625 ((cap_info & 0x08) ? 1626 "Receiver on when idle, " : ""), 1627 ((cap_info & 0x10) ? 1628 "Fast association, " : ""), 1629 ((cap_info & 0x40) ? 1630 "Security supported, " : ""), 1631 ((cap_info & 0x80) ? 1632 "Allocate address, " : "")); 1633 return caplen; 1634 } 1635 break; 1636 case 0x02: /* Association Response */ 1637 if (caplen != 3) { 1638 ND_PRINT("Invalid Association response command length"); 1639 return -1; 1640 } else { 1641 ND_PRINT("Short address = "); 1642 ieee802_15_4_print_addr(ndo, p, 2); 1643 switch (GET_U_1(p + 2)) { 1644 case 0x00: 1645 ND_PRINT(", Association successful"); 1646 break; 1647 case 0x01: 1648 ND_PRINT(", PAN at capacity"); 1649 break; 1650 case 0x02: 1651 ND_PRINT(", PAN access denied"); 1652 break; 1653 case 0x03: 1654 ND_PRINT(", Hooping sequence offset duplication"); 1655 break; 1656 case 0x80: 1657 ND_PRINT(", Fast association successful"); 1658 break; 1659 default: 1660 ND_PRINT(", Status = 0x%02x", 1661 GET_U_1(p + 2)); 1662 break; 1663 } 1664 return caplen; 1665 } 1666 break; 1667 case 0x03: /* Diassociation Notification command */ 1668 if (caplen != 1) { 1669 ND_PRINT("Invalid Disassociation Notification command length"); 1670 return -1; 1671 } else { 1672 switch (GET_U_1(p)) { 1673 case 0x00: 1674 ND_PRINT("Reserved"); 1675 break; 1676 case 0x01: 1677 ND_PRINT("Reason = The coordinator wishes the device to leave PAN"); 1678 break; 1679 case 0x02: 1680 ND_PRINT("Reason = The device wishes to leave the PAN"); 1681 break; 1682 default: 1683 ND_PRINT("Reason = 0x%02x", GET_U_1(p + 2)); 1684 break; 1685 } 1686 return caplen; 1687 } 1688 1689 /* Following ones do not have any data. */ 1690 case 0x04: /* Data Request command */ 1691 case 0x05: /* PAN ID Conflict Notification command */ 1692 case 0x06: /* Orphan Notification command */ 1693 case 0x07: /* Beacon Request command */ 1694 /* Should not have any data. */ 1695 return 0; 1696 case 0x08: /* Coordinator Realignment command */ 1697 if (caplen < 7 || caplen > 8) { 1698 ND_PRINT("Invalid Coordinator Realignment command length"); 1699 return -1; 1700 } else { 1701 uint16_t channel, page; 1702 1703 ND_PRINT("Pan ID = 0x%04x, Coordinator short address = ", 1704 GET_LE_U_2(p)); 1705 ieee802_15_4_print_addr(ndo, p + 2, 2); 1706 channel = GET_U_1(p + 4); 1707 1708 if (caplen == 8) { 1709 page = GET_U_1(p + 7); 1710 } else { 1711 page = 0x80; 1712 } 1713 if (CHECK_BIT(page, 7)) { 1714 /* No page present, instead we have msb of 1715 channel in the page. */ 1716 channel |= (page & 0x7f) << 8; 1717 ND_PRINT(", Channel Number = %d", channel); 1718 } else { 1719 ND_PRINT(", Channel Number = %d, page = %d", 1720 channel, page); 1721 } 1722 ND_PRINT(", Short address = "); 1723 ieee802_15_4_print_addr(ndo, p + 5, 2); 1724 return caplen; 1725 } 1726 break; 1727 case 0x09: /* GTS Request command */ 1728 if (caplen != 1) { 1729 ND_PRINT("Invalid GTS Request command length"); 1730 return -1; 1731 } else { 1732 uint8_t gts; 1733 1734 gts = GET_U_1(p); 1735 ND_PRINT("GTS Length = %d, %s, %s", 1736 gts & 0xf, 1737 (CHECK_BIT(gts, 4) ? 1738 "Receive-only GTS" : "Transmit-only GTS"), 1739 (CHECK_BIT(gts, 5) ? 1740 "GTS allocation" : "GTS deallocations")); 1741 return caplen; 1742 } 1743 break; 1744 case 0x13: /* DSME Association Request command */ 1745 /* XXX Not implemented */ 1746 case 0x14: /* DSME Association Response command */ 1747 /* XXX Not implemented */ 1748 case 0x15: /* DSME GTS Request command */ 1749 /* XXX Not implemented */ 1750 case 0x16: /* DSME GTS Response command */ 1751 /* XXX Not implemented */ 1752 case 0x17: /* DSME GTS Notify command */ 1753 /* XXX Not implemented */ 1754 case 0x18: /* DSME Information Request command */ 1755 /* XXX Not implemented */ 1756 case 0x19: /* DSME Information Response command */ 1757 /* XXX Not implemented */ 1758 case 0x1a: /* DSME Beacon Allocation Notification command */ 1759 /* XXX Not implemented */ 1760 case 0x1b: /* DSME Beacon Collision Notification command */ 1761 /* XXX Not implemented */ 1762 case 0x1c: /* DSME Link Report command */ 1763 /* XXX Not implemented */ 1764 case 0x20: /* RIT Data Request command */ 1765 /* XXX Not implemented */ 1766 case 0x21: /* DBS Request command */ 1767 /* XXX Not implemented */ 1768 case 0x22: /* DBS Response command */ 1769 /* XXX Not implemented */ 1770 case 0x23: /* RIT Data Response command */ 1771 /* XXX Not implemented */ 1772 case 0x24: /* Vendor Specific command */ 1773 /* XXX Not implemented */ 1774 case 0x0a: /* TRLE Management Request command */ 1775 /* XXX Not implemented */ 1776 case 0x0b: /* TRLE Management Response command */ 1777 /* XXX Not implemented */ 1778 default: 1779 ND_PRINT("Command Data = "); 1780 for(i = 0; i < caplen; i++) { 1781 ND_PRINT("%02x ", GET_U_1(p + i)); 1782 } 1783 break; 1784 } 1785 return 0; 1786 } 1787 1788 /* 1789 * Parse and print frames following standard format. 1790 * 1791 * Returns FALSE in case of error. 1792 */ 1793 static u_int 1794 ieee802_15_4_std_frames(netdissect_options *ndo, 1795 const u_char *p, u_int caplen, 1796 uint16_t fc) 1797 { 1798 int len, frame_version, pan_id_comp; 1799 int frame_type; 1800 int src_pan, dst_pan, src_addr_len, dst_addr_len; 1801 int security_level; 1802 u_int miclen = 0; 1803 int payload_ie_present; 1804 uint8_t seq; 1805 uint32_t fcs, crc_check; 1806 const u_char *mic_start = NULL; 1807 1808 payload_ie_present = 0; 1809 1810 crc_check = 0; 1811 /* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not 1812 know about that. */ 1813 if (caplen < 4) { 1814 /* Cannot have FCS, assume no FCS. */ 1815 fcs = 0; 1816 } else { 1817 /* Test for 4 octet FCS. */ 1818 fcs = GET_LE_U_4(p + caplen - 4); 1819 crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4); 1820 if (crc_check == fcs) { 1821 /* Remove FCS */ 1822 caplen -= 4; 1823 } else { 1824 /* Test for 2 octet FCS. */ 1825 fcs = GET_LE_U_2(p + caplen - 2); 1826 crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); 1827 if (crc_check == fcs) { 1828 /* Remove FCS */ 1829 caplen -= 2; 1830 } else { 1831 /* Wrong FCS, FCS might not be included in the 1832 captured frame, do not remove it. */ 1833 } 1834 } 1835 } 1836 1837 /* Frame version. */ 1838 frame_version = FC_FRAME_VERSION(fc); 1839 frame_type = FC_FRAME_TYPE(fc); 1840 ND_PRINT("v%d ", frame_version); 1841 1842 if (ndo->ndo_vflag > 2) { 1843 if (CHECK_BIT(fc, 3)) { ND_PRINT("Security Enabled, "); } 1844 if (CHECK_BIT(fc, 4)) { ND_PRINT("Frame Pending, "); } 1845 if (CHECK_BIT(fc, 5)) { ND_PRINT("AR, "); } 1846 if (CHECK_BIT(fc, 6)) { ND_PRINT("PAN ID Compression, "); } 1847 if (CHECK_BIT(fc, 8)) { ND_PRINT("Sequence Number Suppression, "); } 1848 if (CHECK_BIT(fc, 9)) { ND_PRINT("IE present, "); } 1849 } 1850 1851 /* Check for the sequence number suppression. */ 1852 if (CHECK_BIT(fc, 8)) { 1853 /* Sequence number is suppressed. */ 1854 if (frame_version < 2) { 1855 /* Sequence number can only be suppressed for frame 1856 version 2 or higher, this is invalid frame. */ 1857 ND_PRINT("[ERROR: Sequence number suppressed on frames where version < 2]"); 1858 } 1859 if (ndo->ndo_vflag) 1860 ND_PRINT("seq suppressed "); 1861 if (caplen < 2) { 1862 nd_print_trunc(ndo); 1863 return 0; 1864 } 1865 p += 2; 1866 caplen -= 2; 1867 } else { 1868 seq = GET_U_1(p + 2); 1869 if (ndo->ndo_vflag) 1870 ND_PRINT("seq %02x ", seq); 1871 if (caplen < 3) { 1872 nd_print_trunc(ndo); 1873 return 0; 1874 } 1875 p += 3; 1876 caplen -= 3; 1877 } 1878 1879 /* See which parts of addresses we have. */ 1880 dst_addr_len = ieee802_15_4_addr_len((fc >> 10) & 0x3); 1881 src_addr_len = ieee802_15_4_addr_len((fc >> 14) & 0x3); 1882 if (src_addr_len < 0) { 1883 ND_PRINT("[ERROR: Invalid src address mode]"); 1884 return 0; 1885 } 1886 if (dst_addr_len < 0) { 1887 ND_PRINT("[ERROR: Invalid dst address mode]"); 1888 return 0; 1889 } 1890 src_pan = 0; 1891 dst_pan = 0; 1892 pan_id_comp = CHECK_BIT(fc, 6); 1893 1894 /* The PAN ID Compression rules are complicated. */ 1895 1896 /* First check old versions, where the rules are simple. */ 1897 if (frame_version < 2) { 1898 if (pan_id_comp) { 1899 src_pan = 0; 1900 dst_pan = 1; 1901 if (dst_addr_len <= 0 || src_addr_len <= 0) { 1902 /* Invalid frame, PAN ID Compression must be 0 1903 if only one address in the frame. */ 1904 ND_PRINT("[ERROR: PAN ID Compression != 0, and only one address with frame version < 2]"); 1905 } 1906 } else { 1907 src_pan = 1; 1908 dst_pan = 1; 1909 } 1910 if (dst_addr_len <= 0) { 1911 dst_pan = 0; 1912 } 1913 if (src_addr_len <= 0) { 1914 src_pan = 0; 1915 } 1916 } else { 1917 /* Frame version 2 rules are more complicated, and they depend 1918 on the address modes of the frame, generic rules are same, 1919 but then there are some special cases. */ 1920 if (pan_id_comp) { 1921 src_pan = 0; 1922 dst_pan = 1; 1923 } else { 1924 src_pan = 1; 1925 dst_pan = 1; 1926 } 1927 if (dst_addr_len <= 0) { 1928 dst_pan = 0; 1929 } 1930 if (src_addr_len <= 0) { 1931 src_pan = 0; 1932 } 1933 if (pan_id_comp) { 1934 if (src_addr_len == 0 && 1935 dst_addr_len == 0) { 1936 /* Both addresses are missing, but PAN ID 1937 compression set, special case we have 1938 destination PAN but no addresses. */ 1939 dst_pan = 1; 1940 } else if ((src_addr_len == 0 && 1941 dst_addr_len > 0) || 1942 (src_addr_len > 0 && 1943 dst_addr_len == 0)) { 1944 /* Only one address present, and PAN ID 1945 compression is set, we do not have PAN id at 1946 all. */ 1947 dst_pan = 0; 1948 src_pan = 0; 1949 } else if (src_addr_len == 8 && 1950 dst_addr_len == 8) { 1951 /* Both addresses are Extended, and PAN ID 1952 compression set, we do not have PAN ID at 1953 all. */ 1954 dst_pan = 0; 1955 src_pan = 0; 1956 } 1957 } else { 1958 /* Special cases where PAN ID Compression is not set. */ 1959 if (src_addr_len == 8 && 1960 dst_addr_len == 8) { 1961 /* Both addresses are Extended, and PAN ID 1962 compression not set, we do have only one PAN 1963 ID (destination). */ 1964 dst_pan = 1; 1965 src_pan = 0; 1966 } 1967 #ifdef BROKEN_6TISCH_PAN_ID_COMPRESSION 1968 if (src_addr_len == 8 && 1969 dst_addr_len == 2) { 1970 /* Special case for the broken 6tisch 1971 implementations. */ 1972 src_pan = 0; 1973 } 1974 #endif /* BROKEN_6TISCH_PAN_ID_COMPRESSION */ 1975 } 1976 } 1977 1978 /* Print dst PAN and address. */ 1979 if (dst_pan) { 1980 if (caplen < 2) { 1981 ND_PRINT("[ERROR: Truncated before dst_pan]"); 1982 return 0; 1983 } 1984 ND_PRINT("%04x:", GET_LE_U_2(p)); 1985 p += 2; 1986 caplen -= 2; 1987 } else { 1988 ND_PRINT("-:"); 1989 } 1990 if (caplen < (u_int) dst_addr_len) { 1991 ND_PRINT("[ERROR: Truncated before dst_addr]"); 1992 return 0; 1993 } 1994 ieee802_15_4_print_addr(ndo, p, dst_addr_len); 1995 p += dst_addr_len; 1996 caplen -= dst_addr_len; 1997 1998 ND_PRINT(" < "); 1999 2000 /* Print src PAN and address. */ 2001 if (src_pan) { 2002 if (caplen < 2) { 2003 ND_PRINT("[ERROR: Truncated before dst_pan]"); 2004 return 0; 2005 } 2006 ND_PRINT("%04x:", GET_LE_U_2(p)); 2007 p += 2; 2008 caplen -= 2; 2009 } else { 2010 ND_PRINT("-:"); 2011 } 2012 if (caplen < (u_int) src_addr_len) { 2013 ND_PRINT("[ERROR: Truncated before dst_addr]"); 2014 return 0; 2015 } 2016 ieee802_15_4_print_addr(ndo, p, src_addr_len); 2017 ND_PRINT(" "); 2018 p += src_addr_len; 2019 caplen -= src_addr_len; 2020 if (CHECK_BIT(fc, 3)) { 2021 /* 2022 * XXX - if frame_version is 0, this is the 2003 2023 * spec, and you don't have the auxiliary security 2024 * header, you have a frame counter and key index 2025 * for the AES-CTR and AES-CCM security suites but 2026 * not for the AES-CBC-MAC security suite. 2027 */ 2028 len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen, 2029 &security_level); 2030 if (len < 0) { 2031 return 0; 2032 } 2033 ND_TCHECK_LEN(p, len); 2034 p += len; 2035 caplen -= len; 2036 } else { 2037 security_level = 0; 2038 } 2039 2040 switch (security_level) { 2041 case 0: /*FALLTHOUGH */ 2042 case 4: 2043 miclen = 0; 2044 break; 2045 case 1: /*FALLTHOUGH */ 2046 case 5: 2047 miclen = 4; 2048 break; 2049 case 2: /*FALLTHOUGH */ 2050 case 6: 2051 miclen = 8; 2052 break; 2053 case 3: /*FALLTHOUGH */ 2054 case 7: 2055 miclen = 16; 2056 break; 2057 } 2058 2059 /* Remove MIC */ 2060 if (miclen != 0) { 2061 if (caplen < miclen) { 2062 ND_PRINT("[ERROR: Truncated before MIC]"); 2063 return 0; 2064 } 2065 caplen -= miclen; 2066 mic_start = p + caplen; 2067 } 2068 2069 /* Parse Information elements if present */ 2070 if (CHECK_BIT(fc, 9)) { 2071 /* Yes we have those. */ 2072 len = ieee802_15_4_print_header_ie_list(ndo, p, caplen, 2073 &payload_ie_present); 2074 if (len < 0) { 2075 return 0; 2076 } 2077 p += len; 2078 caplen -= len; 2079 } 2080 2081 if (payload_ie_present) { 2082 if (security_level >= 4) { 2083 ND_PRINT("Payload IEs present, but encrypted, cannot print "); 2084 } else { 2085 len = ieee802_15_4_print_payload_ie_list(ndo, p, caplen); 2086 if (len < 0) { 2087 return 0; 2088 } 2089 p += len; 2090 caplen -= len; 2091 } 2092 } 2093 2094 /* Print MIC */ 2095 if (ndo->ndo_vflag > 2 && miclen != 0) { 2096 ND_PRINT("\n\tMIC "); 2097 2098 for (u_int micoffset = 0; micoffset < miclen; micoffset++) { 2099 ND_PRINT("%02x", GET_U_1(mic_start + micoffset)); 2100 } 2101 ND_PRINT(" "); 2102 } 2103 2104 /* Print FCS */ 2105 if (ndo->ndo_vflag > 2) { 2106 if (crc_check == fcs) { 2107 ND_PRINT("FCS %x ", fcs); 2108 } else { 2109 ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ", 2110 fcs, crc_check); 2111 } 2112 } 2113 2114 /* Payload print */ 2115 switch (frame_type) { 2116 case 0x00: /* Beacon */ 2117 if (frame_version < 2) { 2118 if (caplen < 2) { 2119 ND_PRINT("[ERROR: Truncated before beacon information]"); 2120 break; 2121 } else { 2122 uint16_t ss; 2123 2124 ss = GET_LE_U_2(p); 2125 ieee802_15_4_print_superframe_specification(ndo, ss); 2126 p += 2; 2127 caplen -= 2; 2128 2129 /* GTS */ 2130 if (caplen < 1) { 2131 ND_PRINT("[ERROR: Truncated before GTS info]"); 2132 break; 2133 } 2134 2135 len = ieee802_15_4_print_gts_info(ndo, p, caplen); 2136 if (len < 0) { 2137 break; 2138 } 2139 2140 p += len; 2141 caplen -= len; 2142 2143 /* Pending Addresses */ 2144 if (caplen < 1) { 2145 ND_PRINT("[ERROR: Truncated before pending addresses]"); 2146 break; 2147 } 2148 len = ieee802_15_4_print_pending_addresses(ndo, p, caplen); 2149 if (len < 0) { 2150 break; 2151 } 2152 ND_TCHECK_LEN(p, len); 2153 p += len; 2154 caplen -= len; 2155 } 2156 } 2157 if (!ndo->ndo_suppress_default_print) 2158 ND_DEFAULTPRINT(p, caplen); 2159 2160 break; 2161 case 0x01: /* Data */ 2162 case 0x02: /* Acknowledgement */ 2163 if (!ndo->ndo_suppress_default_print) 2164 ND_DEFAULTPRINT(p, caplen); 2165 break; 2166 case 0x03: /* MAC Command */ 2167 if (caplen < 1) { 2168 ND_PRINT("[ERROR: Truncated before Command ID]"); 2169 } else { 2170 uint8_t command_id; 2171 2172 command_id = GET_U_1(p); 2173 if (command_id >= 0x30) { 2174 ND_PRINT("Command ID = Reserved 0x%02x ", 2175 command_id); 2176 } else { 2177 ND_PRINT("Command ID = %s ", 2178 mac_c_names[command_id]); 2179 } 2180 p++; 2181 caplen--; 2182 if (caplen != 0) { 2183 len = ieee802_15_4_print_command_data(ndo, command_id, p, caplen); 2184 if (len >= 0) { 2185 p += len; 2186 caplen -= len; 2187 } 2188 } 2189 } 2190 if (!ndo->ndo_suppress_default_print) 2191 ND_DEFAULTPRINT(p, caplen); 2192 break; 2193 } 2194 return 1; 2195 } 2196 2197 /* 2198 * Print and parse Multipurpose frames. 2199 * 2200 * Returns FALSE in case of error. 2201 */ 2202 static u_int 2203 ieee802_15_4_mp_frame(netdissect_options *ndo, 2204 const u_char *p, u_int caplen, 2205 uint16_t fc) 2206 { 2207 int len, frame_version, pan_id_present; 2208 int src_addr_len, dst_addr_len; 2209 int security_level; 2210 u_int miclen = 0; 2211 int ie_present, payload_ie_present, security_enabled; 2212 uint8_t seq; 2213 uint32_t fcs, crc_check; 2214 const u_char *mic_start = NULL; 2215 2216 pan_id_present = 0; 2217 ie_present = 0; 2218 payload_ie_present = 0; 2219 security_enabled = 0; 2220 crc_check = 0; 2221 2222 /* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not 2223 know about that. */ 2224 if (caplen < 3) { 2225 /* Cannot have FCS, assume no FCS. */ 2226 fcs = 0; 2227 } else { 2228 if (caplen > 4) { 2229 /* Test for 4 octet FCS. */ 2230 fcs = GET_LE_U_4(p + caplen - 4); 2231 crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4); 2232 if (crc_check == fcs) { 2233 /* Remove FCS */ 2234 caplen -= 4; 2235 } else { 2236 fcs = GET_LE_U_2(p + caplen - 2); 2237 crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); 2238 if (crc_check == fcs) { 2239 /* Remove FCS */ 2240 caplen -= 2; 2241 } 2242 } 2243 } else { 2244 fcs = GET_LE_U_2(p + caplen - 2); 2245 crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); 2246 if (crc_check == fcs) { 2247 /* Remove FCS */ 2248 caplen -= 2; 2249 } 2250 } 2251 } 2252 2253 if (CHECK_BIT(fc, 3)) { 2254 /* Long Frame Control */ 2255 2256 /* Frame version. */ 2257 frame_version = FC_FRAME_VERSION(fc); 2258 ND_PRINT("v%d ", frame_version); 2259 2260 pan_id_present = CHECK_BIT(fc, 8); 2261 ie_present = CHECK_BIT(fc, 15); 2262 security_enabled = CHECK_BIT(fc, 9); 2263 2264 if (ndo->ndo_vflag > 2) { 2265 if (security_enabled) { ND_PRINT("Security Enabled, "); } 2266 if (CHECK_BIT(fc, 11)) { ND_PRINT("Frame Pending, "); } 2267 if (CHECK_BIT(fc, 14)) { ND_PRINT("AR, "); } 2268 if (pan_id_present) { ND_PRINT("PAN ID Present, "); } 2269 if (CHECK_BIT(fc, 10)) { 2270 ND_PRINT("Sequence Number Suppression, "); 2271 } 2272 if (ie_present) { ND_PRINT("IE present, "); } 2273 } 2274 2275 /* Check for the sequence number suppression. */ 2276 if (CHECK_BIT(fc, 10)) { 2277 /* Sequence number is suppressed, but long version. */ 2278 if (caplen < 2) { 2279 nd_print_trunc(ndo); 2280 return 0; 2281 } 2282 p += 2; 2283 caplen -= 2; 2284 } else { 2285 seq = GET_U_1(p + 2); 2286 if (ndo->ndo_vflag) 2287 ND_PRINT("seq %02x ", seq); 2288 if (caplen < 3) { 2289 nd_print_trunc(ndo); 2290 return 0; 2291 } 2292 p += 3; 2293 caplen -= 3; 2294 } 2295 } else { 2296 /* Short format of header, but with seq no */ 2297 seq = GET_U_1(p + 1); 2298 p += 2; 2299 caplen -= 2; 2300 if (ndo->ndo_vflag) 2301 ND_PRINT("seq %02x ", seq); 2302 } 2303 2304 /* See which parts of addresses we have. */ 2305 dst_addr_len = ieee802_15_4_addr_len((fc >> 4) & 0x3); 2306 src_addr_len = ieee802_15_4_addr_len((fc >> 6) & 0x3); 2307 if (src_addr_len < 0) { 2308 ND_PRINT("[ERROR: Invalid src address mode]"); 2309 return 0; 2310 } 2311 if (dst_addr_len < 0) { 2312 ND_PRINT("[ERROR: Invalid dst address mode]"); 2313 return 0; 2314 } 2315 2316 /* Print dst PAN and address. */ 2317 if (pan_id_present) { 2318 if (caplen < 2) { 2319 ND_PRINT("[ERROR: Truncated before dst_pan]"); 2320 return 0; 2321 } 2322 ND_PRINT("%04x:", GET_LE_U_2(p)); 2323 p += 2; 2324 caplen -= 2; 2325 } else { 2326 ND_PRINT("-:"); 2327 } 2328 if (caplen < (u_int) dst_addr_len) { 2329 ND_PRINT("[ERROR: Truncated before dst_addr]"); 2330 return 0; 2331 } 2332 ieee802_15_4_print_addr(ndo, p, dst_addr_len); 2333 p += dst_addr_len; 2334 caplen -= dst_addr_len; 2335 2336 ND_PRINT(" < "); 2337 2338 /* Print src PAN and address. */ 2339 ND_PRINT(" -:"); 2340 if (caplen < (u_int) src_addr_len) { 2341 ND_PRINT("[ERROR: Truncated before dst_addr]"); 2342 return 0; 2343 } 2344 ieee802_15_4_print_addr(ndo, p, src_addr_len); 2345 ND_PRINT(" "); 2346 p += src_addr_len; 2347 caplen -= src_addr_len; 2348 2349 if (security_enabled) { 2350 len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen, 2351 &security_level); 2352 if (len < 0) { 2353 return 0; 2354 } 2355 ND_TCHECK_LEN(p, len); 2356 p += len; 2357 caplen -= len; 2358 } else { 2359 security_level = 0; 2360 } 2361 2362 switch (security_level) { 2363 case 0: /*FALLTHOUGH */ 2364 case 4: 2365 miclen = 0; 2366 break; 2367 case 1: /*FALLTHOUGH */ 2368 case 5: 2369 miclen = 4; 2370 break; 2371 case 2: /*FALLTHOUGH */ 2372 case 6: 2373 miclen = 8; 2374 break; 2375 case 3: /*FALLTHOUGH */ 2376 case 7: 2377 miclen = 16; 2378 break; 2379 } 2380 2381 /* Remove MIC */ 2382 if (miclen != 0) { 2383 if (caplen < miclen) { 2384 ND_PRINT("[ERROR: Truncated before MIC]"); 2385 return 0; 2386 } 2387 caplen -= miclen; 2388 mic_start = p + caplen; 2389 } 2390 2391 /* Parse Information elements if present */ 2392 if (ie_present) { 2393 /* Yes we have those. */ 2394 len = ieee802_15_4_print_header_ie_list(ndo, p, caplen, 2395 &payload_ie_present); 2396 if (len < 0) { 2397 return 0; 2398 } 2399 p += len; 2400 caplen -= len; 2401 } 2402 2403 if (payload_ie_present) { 2404 if (security_level >= 4) { 2405 ND_PRINT("Payload IEs present, but encrypted, cannot print "); 2406 } else { 2407 len = ieee802_15_4_print_payload_ie_list(ndo, p, 2408 caplen); 2409 if (len < 0) { 2410 return 0; 2411 } 2412 p += len; 2413 caplen -= len; 2414 } 2415 } 2416 2417 /* Print MIC */ 2418 if (ndo->ndo_vflag > 2 && miclen != 0) { 2419 ND_PRINT("\n\tMIC "); 2420 2421 for (u_int micoffset = 0; micoffset < miclen; micoffset++) { 2422 ND_PRINT("%02x", GET_U_1(mic_start + micoffset)); 2423 } 2424 ND_PRINT(" "); 2425 } 2426 2427 2428 /* Print FCS */ 2429 if (ndo->ndo_vflag > 2) { 2430 if (crc_check == fcs) { 2431 ND_PRINT("FCS %x ", fcs); 2432 } else { 2433 ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ", 2434 fcs, crc_check); 2435 } 2436 } 2437 2438 if (!ndo->ndo_suppress_default_print) 2439 ND_DEFAULTPRINT(p, caplen); 2440 2441 return 1; 2442 } 2443 2444 /* 2445 * Print frag frame. 2446 * 2447 * Returns FALSE in case of error. 2448 */ 2449 static u_int 2450 ieee802_15_4_frag_frame(netdissect_options *ndo _U_, 2451 const u_char *p _U_, 2452 u_int caplen _U_, 2453 uint16_t fc _U_) 2454 { 2455 /* Not implement yet, might be bit hard to implement, as the 2456 * information to set up the fragment is coming in the previous frame 2457 * in the Fragment Sequence Context Description IE, thus we need to 2458 * store information from there, so we can use it here. */ 2459 return 0; 2460 } 2461 2462 /* 2463 * Internal call to dissector taking packet + len instead of pcap_pkthdr. 2464 * 2465 * Returns FALSE in case of error. 2466 */ 2467 u_int 2468 ieee802_15_4_print(netdissect_options *ndo, 2469 const u_char *p, u_int caplen) 2470 { 2471 int frame_type; 2472 uint16_t fc; 2473 2474 ndo->ndo_protocol = "802.15.4"; 2475 2476 if (caplen < 2) { 2477 nd_print_trunc(ndo); 2478 return caplen; 2479 } 2480 2481 fc = GET_LE_U_2(p); 2482 2483 /* First we need to check the frame type to know how to parse the rest 2484 of the FC. Frame type is the first 3 bit of the frame control field. 2485 */ 2486 2487 frame_type = FC_FRAME_TYPE(fc); 2488 ND_PRINT("IEEE 802.15.4 %s packet ", ftypes[frame_type]); 2489 2490 switch (frame_type) { 2491 case 0x00: /* Beacon */ 2492 case 0x01: /* Data */ 2493 case 0x02: /* Acknowledgement */ 2494 case 0x03: /* MAC Command */ 2495 return ieee802_15_4_std_frames(ndo, p, caplen, fc); 2496 break; 2497 case 0x04: /* Reserved */ 2498 return 0; 2499 break; 2500 case 0x05: /* Multipurpose */ 2501 return ieee802_15_4_mp_frame(ndo, p, caplen, fc); 2502 break; 2503 case 0x06: /* Fragment or Frak */ 2504 return ieee802_15_4_frag_frame(ndo, p, caplen, fc); 2505 break; 2506 case 0x07: /* Extended */ 2507 return 0; 2508 break; 2509 } 2510 return 0; 2511 } 2512 2513 /* 2514 * Main function to print packets. 2515 */ 2516 2517 void 2518 ieee802_15_4_if_print(netdissect_options *ndo, 2519 const struct pcap_pkthdr *h, const u_char *p) 2520 { 2521 u_int caplen = h->caplen; 2522 ndo->ndo_protocol = "802.15.4"; 2523 ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p, caplen); 2524 } 2525 2526 /* For DLT_IEEE802_15_4_TAP */ 2527 /* https://github.com/jkcko/ieee802.15.4-tap */ 2528 void 2529 ieee802_15_4_tap_if_print(netdissect_options *ndo, 2530 const struct pcap_pkthdr *h, const u_char *p) 2531 { 2532 uint8_t version; 2533 uint16_t length; 2534 2535 ndo->ndo_protocol = "802.15.4_tap"; 2536 if (h->caplen < 4) { 2537 nd_print_trunc(ndo); 2538 ndo->ndo_ll_hdr_len += h->caplen; 2539 return; 2540 } 2541 2542 version = GET_U_1(p); 2543 length = GET_LE_U_2(p + 2); 2544 if (version != 0 || length < 4) { 2545 nd_print_invalid(ndo); 2546 return; 2547 } 2548 2549 if (h->caplen < length) { 2550 nd_print_trunc(ndo); 2551 ndo->ndo_ll_hdr_len += h->caplen; 2552 return; 2553 } 2554 2555 ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p+length, h->caplen-length) + length; 2556 } 2557