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 23235427Sdelphij#ifdef HAVE_CONFIG_H 24235427Sdelphij#include "config.h" 25235427Sdelphij#endif 26235427Sdelphij 27235427Sdelphij#include <tcpdump-stdinc.h> 28235427Sdelphij 29235427Sdelphij#include <stdio.h> 30235427Sdelphij#include <pcap.h> 31235427Sdelphij#include <string.h> 32235427Sdelphij 33235427Sdelphij#include "interface.h" 34235427Sdelphij#include "addrtoname.h" 35235427Sdelphij 36235427Sdelphij#include "extract.h" 37235427Sdelphij 38235427Sdelphijstatic const char *ftypes[] = { 39235427Sdelphij "Beacon", /* 0 */ 40235427Sdelphij "Data", /* 1 */ 41235427Sdelphij "ACK", /* 2 */ 42235427Sdelphij "Command", /* 3 */ 43235427Sdelphij "Reserved", /* 4 */ 44235427Sdelphij "Reserved", /* 5 */ 45235427Sdelphij "Reserved", /* 6 */ 46235427Sdelphij "Reserved", /* 7 */ 47235427Sdelphij}; 48235427Sdelphij 49235427Sdelphijstatic int 50235427Sdelphijextract_header_length(u_int16_t fc) 51235427Sdelphij{ 52235427Sdelphij int len = 0; 53235427Sdelphij 54235427Sdelphij switch ((fc >> 10) & 0x3) { 55235427Sdelphij case 0x00: 56235427Sdelphij if (fc & (1 << 6)) /* intra-PAN with none dest addr */ 57235427Sdelphij return -1; 58235427Sdelphij break; 59235427Sdelphij case 0x01: 60235427Sdelphij return -1; 61235427Sdelphij case 0x02: 62235427Sdelphij len += 4; 63235427Sdelphij break; 64235427Sdelphij case 0x03: 65235427Sdelphij len += 10; 66235427Sdelphij break; 67235427Sdelphij } 68235427Sdelphij 69235427Sdelphij switch ((fc >> 14) & 0x3) { 70235427Sdelphij case 0x00: 71235427Sdelphij break; 72235427Sdelphij case 0x01: 73235427Sdelphij return -1; 74235427Sdelphij case 0x02: 75235427Sdelphij len += 4; 76235427Sdelphij break; 77235427Sdelphij case 0x03: 78235427Sdelphij len += 10; 79235427Sdelphij break; 80235427Sdelphij } 81235427Sdelphij 82235427Sdelphij if (fc & (1 << 6)) { 83235427Sdelphij if (len < 2) 84235427Sdelphij return -1; 85235427Sdelphij len -= 2; 86235427Sdelphij } 87235427Sdelphij 88235427Sdelphij return len; 89235427Sdelphij} 90235427Sdelphij 91235427Sdelphij 92235427Sdelphiju_int 93235427Sdelphijieee802_15_4_if_print(struct netdissect_options *ndo, 94235427Sdelphij const struct pcap_pkthdr *h, const u_char *p) 95235427Sdelphij{ 96235427Sdelphij u_int caplen = h->caplen; 97235427Sdelphij int hdrlen; 98235427Sdelphij u_int16_t fc; 99235427Sdelphij u_int8_t seq; 100235427Sdelphij 101235427Sdelphij if (caplen < 3) { 102235427Sdelphij ND_PRINT((ndo, "[|802.15.4] %x", caplen)); 103235427Sdelphij return caplen; 104235427Sdelphij } 105235427Sdelphij 106235427Sdelphij fc = EXTRACT_LE_16BITS(p); 107235427Sdelphij hdrlen = extract_header_length(fc); 108235427Sdelphij 109235427Sdelphij seq = EXTRACT_LE_8BITS(p + 2); 110235427Sdelphij 111235427Sdelphij p += 3; 112235427Sdelphij caplen -= 3; 113235427Sdelphij 114235427Sdelphij ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7])); 115235427Sdelphij if (vflag) 116235427Sdelphij ND_PRINT((ndo,"seq %02x ", seq)); 117235427Sdelphij if (hdrlen == -1) { 118235427Sdelphij ND_PRINT((ndo,"malformed! ")); 119235427Sdelphij return caplen; 120235427Sdelphij } 121235427Sdelphij 122235427Sdelphij 123235427Sdelphij if (!vflag) { 124235427Sdelphij p+= hdrlen; 125235427Sdelphij caplen -= hdrlen; 126235427Sdelphij } else { 127235427Sdelphij u_int16_t panid = 0; 128235427Sdelphij 129235427Sdelphij switch ((fc >> 10) & 0x3) { 130235427Sdelphij case 0x00: 131235427Sdelphij ND_PRINT((ndo,"none ")); 132235427Sdelphij break; 133235427Sdelphij case 0x01: 134235427Sdelphij ND_PRINT((ndo,"reserved destination addressing mode")); 135235427Sdelphij return 0; 136235427Sdelphij case 0x02: 137235427Sdelphij panid = EXTRACT_LE_16BITS(p); 138235427Sdelphij p += 2; 139235427Sdelphij ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 140235427Sdelphij p += 2; 141235427Sdelphij break; 142235427Sdelphij case 0x03: 143235427Sdelphij panid = EXTRACT_LE_16BITS(p); 144235427Sdelphij p += 2; 145235427Sdelphij ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p))); 146235427Sdelphij p += 8; 147235427Sdelphij break; 148235427Sdelphij } 149235427Sdelphij ND_PRINT((ndo,"< "); 150235427Sdelphij 151235427Sdelphij switch ((fc >> 14) & 0x3) { 152235427Sdelphij case 0x00: 153235427Sdelphij ND_PRINT((ndo,"none ")); 154235427Sdelphij break; 155235427Sdelphij case 0x01: 156235427Sdelphij ND_PRINT((ndo,"reserved source addressing mode")); 157235427Sdelphij return 0; 158235427Sdelphij case 0x02: 159235427Sdelphij if (!(fc & (1 << 6))) { 160235427Sdelphij panid = EXTRACT_LE_16BITS(p); 161235427Sdelphij p += 2; 162235427Sdelphij } 163235427Sdelphij ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 164235427Sdelphij p += 2; 165235427Sdelphij break; 166235427Sdelphij case 0x03: 167235427Sdelphij if (!(fc & (1 << 6))) { 168235427Sdelphij panid = EXTRACT_LE_16BITS(p); 169235427Sdelphij p += 2; 170235427Sdelphij } 171235427Sdelphij ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p)))); 172235427Sdelphij p += 8; 173235427Sdelphij break; 174235427Sdelphij } 175235427Sdelphij 176235427Sdelphij caplen -= hdrlen; 177235427Sdelphij } 178235427Sdelphij 179235427Sdelphij if (!suppress_default_print) 180235427Sdelphij (ndo->ndo_default_print)(ndo, p, caplen); 181235427Sdelphij 182235427Sdelphij return 0; 183235427Sdelphij} 184