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