1235427Sdelphij/* 2235427Sdelphij * Copyright (c) 2009 3235427Sdelphij * Siemens AG, All rights reserved. 4235427Sdelphij * Dmitry Eremin-Solenikov (dbaryshkov@gmail.com) 5235427Sdelphij * 6235427Sdelphij * Redistribution and use in source and binary forms, with or without 7235427Sdelphij * modification, are permitted provided that: (1) source code distributions 8235427Sdelphij * retain the above copyright notice and this paragraph in its entirety, (2) 9235427Sdelphij * distributions including binary code include the above copyright notice and 10235427Sdelphij * this paragraph in its entirety in the documentation or other materials 11235427Sdelphij * provided with the distribution, and (3) all advertising materials mentioning 12235427Sdelphij * features or use of this software display the following acknowledgement: 13235427Sdelphij * ``This product includes software developed by the University of California, 14235427Sdelphij * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 15235427Sdelphij * the University nor the names of its contributors may be used to endorse 16235427Sdelphij * or promote products derived from this software without specific prior 17235427Sdelphij * written permission. 18235427Sdelphij * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 19235427Sdelphij * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 20235427Sdelphij * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21235427Sdelphij */ 22235427Sdelphij 23313537Sglebius/* \summary: IEEE 802.15.4 printer */ 24313537Sglebius 25235427Sdelphij#ifdef HAVE_CONFIG_H 26235427Sdelphij#include "config.h" 27235427Sdelphij#endif 28235427Sdelphij 29313537Sglebius#include <netdissect-stdinc.h> 30235427Sdelphij 31313537Sglebius#include "netdissect.h" 32235427Sdelphij#include "addrtoname.h" 33235427Sdelphij 34235427Sdelphij#include "extract.h" 35235427Sdelphij 36235427Sdelphijstatic const char *ftypes[] = { 37235427Sdelphij "Beacon", /* 0 */ 38235427Sdelphij "Data", /* 1 */ 39235427Sdelphij "ACK", /* 2 */ 40235427Sdelphij "Command", /* 3 */ 41327234Semaste "Reserved (0x4)", /* 4 */ 42327234Semaste "Reserved (0x5)", /* 5 */ 43327234Semaste "Reserved (0x6)", /* 6 */ 44327234Semaste "Reserved (0x7)", /* 7 */ 45235427Sdelphij}; 46235427Sdelphij 47327234Semaste/* 48327234Semaste * Frame Control subfields. 49327234Semaste */ 50327234Semaste#define FC_FRAME_TYPE(fc) ((fc) & 0x7) 51327234Semaste#define FC_SECURITY_ENABLED 0x0008 52327234Semaste#define FC_FRAME_PENDING 0x0010 53327234Semaste#define FC_ACK_REQUEST 0x0020 54327234Semaste#define FC_PAN_ID_COMPRESSION 0x0040 55327234Semaste#define FC_DEST_ADDRESSING_MODE(fc) (((fc) >> 10) & 0x3) 56327234Semaste#define FC_FRAME_VERSION(fc) (((fc) >> 12) & 0x3) 57327234Semaste#define FC_SRC_ADDRESSING_MODE(fc) (((fc) >> 14) & 0x3) 58235427Sdelphij 59327234Semaste#define FC_ADDRESSING_MODE_NONE 0x00 60327234Semaste#define FC_ADDRESSING_MODE_RESERVED 0x01 61327234Semaste#define FC_ADDRESSING_MODE_SHORT 0x02 62327234Semaste#define FC_ADDRESSING_MODE_LONG 0x03 63235427Sdelphij 64235427Sdelphiju_int 65276788Sdelphijieee802_15_4_if_print(netdissect_options *ndo, 66235427Sdelphij const struct pcap_pkthdr *h, const u_char *p) 67235427Sdelphij{ 68235427Sdelphij u_int caplen = h->caplen; 69327234Semaste u_int hdrlen; 70276788Sdelphij uint16_t fc; 71276788Sdelphij uint8_t seq; 72327234Semaste uint16_t panid = 0; 73235427Sdelphij 74235427Sdelphij if (caplen < 3) { 75327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 76235427Sdelphij return caplen; 77235427Sdelphij } 78327234Semaste hdrlen = 3; 79235427Sdelphij 80235427Sdelphij fc = EXTRACT_LE_16BITS(p); 81235427Sdelphij seq = EXTRACT_LE_8BITS(p + 2); 82235427Sdelphij 83235427Sdelphij p += 3; 84235427Sdelphij caplen -= 3; 85235427Sdelphij 86327234Semaste ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[FC_FRAME_TYPE(fc)])); 87276788Sdelphij if (ndo->ndo_vflag) 88235427Sdelphij ND_PRINT((ndo,"seq %02x ", seq)); 89235427Sdelphij 90327234Semaste /* 91327234Semaste * Destination address and PAN ID, if present. 92327234Semaste */ 93327234Semaste switch (FC_DEST_ADDRESSING_MODE(fc)) { 94327234Semaste case FC_ADDRESSING_MODE_NONE: 95327234Semaste if (fc & FC_PAN_ID_COMPRESSION) { 96327234Semaste /* 97327234Semaste * PAN ID compression; this requires that both 98327234Semaste * the source and destination addresses be present, 99327234Semaste * but the destination address is missing. 100327234Semaste */ 101327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 102327234Semaste return hdrlen; 103327234Semaste } 104327234Semaste if (ndo->ndo_vflag) 105235427Sdelphij ND_PRINT((ndo,"none ")); 106327234Semaste break; 107327234Semaste case FC_ADDRESSING_MODE_RESERVED: 108327234Semaste if (ndo->ndo_vflag) 109235427Sdelphij ND_PRINT((ndo,"reserved destination addressing mode")); 110327234Semaste return hdrlen; 111327234Semaste case FC_ADDRESSING_MODE_SHORT: 112327234Semaste if (caplen < 2) { 113327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 114327234Semaste return hdrlen; 115327234Semaste } 116327234Semaste panid = EXTRACT_LE_16BITS(p); 117327234Semaste p += 2; 118327234Semaste caplen -= 2; 119327234Semaste hdrlen += 2; 120327234Semaste if (caplen < 2) { 121327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 122327234Semaste return hdrlen; 123327234Semaste } 124327234Semaste if (ndo->ndo_vflag) 125235427Sdelphij ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 126327234Semaste p += 2; 127327234Semaste caplen -= 2; 128327234Semaste hdrlen += 2; 129327234Semaste break; 130327234Semaste case FC_ADDRESSING_MODE_LONG: 131327234Semaste if (caplen < 2) { 132327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 133327234Semaste return hdrlen; 134327234Semaste } 135327234Semaste panid = EXTRACT_LE_16BITS(p); 136327234Semaste p += 2; 137327234Semaste caplen -= 2; 138327234Semaste hdrlen += 2; 139327234Semaste if (caplen < 8) { 140327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 141327234Semaste return hdrlen; 142327234Semaste } 143327234Semaste if (ndo->ndo_vflag) 144313537Sglebius ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); 145327234Semaste p += 8; 146327234Semaste caplen -= 8; 147327234Semaste hdrlen += 8; 148327234Semaste break; 149327234Semaste } 150327234Semaste if (ndo->ndo_vflag) 151276788Sdelphij ND_PRINT((ndo,"< ")); 152235427Sdelphij 153327234Semaste /* 154327234Semaste * Source address and PAN ID, if present. 155327234Semaste */ 156327234Semaste switch (FC_SRC_ADDRESSING_MODE(fc)) { 157327234Semaste case FC_ADDRESSING_MODE_NONE: 158327234Semaste if (ndo->ndo_vflag) 159235427Sdelphij ND_PRINT((ndo,"none ")); 160327234Semaste break; 161327234Semaste case FC_ADDRESSING_MODE_RESERVED: 162327234Semaste if (ndo->ndo_vflag) 163235427Sdelphij ND_PRINT((ndo,"reserved source addressing mode")); 164327234Semaste return 0; 165327234Semaste case FC_ADDRESSING_MODE_SHORT: 166327234Semaste if (!(fc & FC_PAN_ID_COMPRESSION)) { 167327234Semaste /* 168327234Semaste * The source PAN ID is not compressed out, so 169327234Semaste * fetch it. (Otherwise, we'll use the destination 170327234Semaste * PAN ID, fetched above.) 171327234Semaste */ 172327234Semaste if (caplen < 2) { 173327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 174327234Semaste return hdrlen; 175235427Sdelphij } 176327234Semaste panid = EXTRACT_LE_16BITS(p); 177327234Semaste p += 2; 178327234Semaste caplen -= 2; 179327234Semaste hdrlen += 2; 180327234Semaste } 181327234Semaste if (caplen < 2) { 182327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 183327234Semaste return hdrlen; 184327234Semaste } 185327234Semaste if (ndo->ndo_vflag) 186235427Sdelphij ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 187327234Semaste p += 2; 188327234Semaste caplen -= 2; 189327234Semaste hdrlen += 2; 190327234Semaste break; 191327234Semaste case FC_ADDRESSING_MODE_LONG: 192327234Semaste if (!(fc & FC_PAN_ID_COMPRESSION)) { 193327234Semaste /* 194327234Semaste * The source PAN ID is not compressed out, so 195327234Semaste * fetch it. (Otherwise, we'll use the destination 196327234Semaste * PAN ID, fetched above.) 197327234Semaste */ 198327234Semaste if (caplen < 2) { 199327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 200327234Semaste return hdrlen; 201327234Semaste } 202327234Semaste panid = EXTRACT_LE_16BITS(p); 203235427Sdelphij p += 2; 204327234Semaste caplen -= 2; 205327234Semaste hdrlen += 2; 206235427Sdelphij } 207327234Semaste if (caplen < 8) { 208327234Semaste ND_PRINT((ndo, "[|802.15.4]")); 209327234Semaste return hdrlen; 210327234Semaste } 211327234Semaste if (ndo->ndo_vflag) 212327234Semaste ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); 213327234Semaste p += 8; 214327234Semaste caplen -= 8; 215327234Semaste hdrlen += 8; 216327234Semaste break; 217235427Sdelphij } 218235427Sdelphij 219276788Sdelphij if (!ndo->ndo_suppress_default_print) 220276788Sdelphij ND_DEFAULTPRINT(p, caplen); 221235427Sdelphij 222327234Semaste return hdrlen; 223235427Sdelphij} 224