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