print-802_15_4.c revision 235427
182867Sdfr/* 2139790Simp * Copyright (c) 2009 3139790Simp * Siemens AG, All rights reserved. 482867Sdfr * Dmitry Eremin-Solenikov (dbaryshkov@gmail.com) 582867Sdfr * 682867Sdfr * Redistribution and use in source and binary forms, with or without 782867Sdfr * modification, are permitted provided that: (1) source code distributions 882867Sdfr * retain the above copyright notice and this paragraph in its entirety, (2) 982867Sdfr * distributions including binary code include the above copyright notice and 1082867Sdfr * this paragraph in its entirety in the documentation or other materials 1182867Sdfr * provided with the distribution, and (3) all advertising materials mentioning 1282867Sdfr * features or use of this software display the following acknowledgement: 1382867Sdfr * ``This product includes software developed by the University of California, 1482867Sdfr * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1582867Sdfr * the University nor the names of its contributors may be used to endorse 1682867Sdfr * or promote products derived from this software without specific prior 1782867Sdfr * written permission. 1882867Sdfr * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1982867Sdfr * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 2082867Sdfr * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2182867Sdfr */ 2282867Sdfr 2382867Sdfr#ifdef HAVE_CONFIG_H 2482867Sdfr#include "config.h" 2582867Sdfr#endif 2682867Sdfr 2782867Sdfr#include <tcpdump-stdinc.h> 2882867Sdfr 2982867Sdfr#include <stdio.h> 3082867Sdfr#include <pcap.h> 3182867Sdfr#include <string.h> 3282867Sdfr 3382867Sdfr#include "interface.h" 3482867Sdfr#include "addrtoname.h" 3582867Sdfr 3682867Sdfr#include "extract.h" 3782867Sdfr 3882867Sdfrstatic const char *ftypes[] = { 3982867Sdfr "Beacon", /* 0 */ 4082867Sdfr "Data", /* 1 */ 4182867Sdfr "ACK", /* 2 */ 4282867Sdfr "Command", /* 3 */ 4382867Sdfr "Reserved", /* 4 */ 4482867Sdfr "Reserved", /* 5 */ 4582867Sdfr "Reserved", /* 6 */ 4682867Sdfr "Reserved", /* 7 */ 4782867Sdfr}; 4882867Sdfr 4982867Sdfrstatic int 5082867Sdfrextract_header_length(u_int16_t fc) 5182867Sdfr{ 5282867Sdfr int len = 0; 5382867Sdfr 5482867Sdfr switch ((fc >> 10) & 0x3) { 5582867Sdfr case 0x00: 5682867Sdfr if (fc & (1 << 6)) /* intra-PAN with none dest addr */ 5782867Sdfr return -1; 5882867Sdfr break; 5982867Sdfr case 0x01: 6082867Sdfr return -1; 6182867Sdfr case 0x02: 6282867Sdfr len += 4; 6382867Sdfr break; 6482867Sdfr case 0x03: 6582867Sdfr len += 10; 6682867Sdfr break; 6782867Sdfr } 6882867Sdfr 6982867Sdfr switch ((fc >> 14) & 0x3) { 7082867Sdfr case 0x00: 7182867Sdfr break; 7282867Sdfr case 0x01: 7382867Sdfr return -1; 7482867Sdfr case 0x02: 7582867Sdfr len += 4; 7682867Sdfr break; 7782867Sdfr case 0x03: 7882867Sdfr len += 10; 7982867Sdfr break; 8082867Sdfr } 8182867Sdfr 8282867Sdfr if (fc & (1 << 6)) { 8382867Sdfr if (len < 2) 8482867Sdfr return -1; 8582867Sdfr len -= 2; 8682867Sdfr } 8782867Sdfr 8882867Sdfr return len; 8982867Sdfr} 9082867Sdfr 9182867Sdfr 9282867Sdfru_int 9382867Sdfrieee802_15_4_if_print(struct netdissect_options *ndo, 9482867Sdfr const struct pcap_pkthdr *h, const u_char *p) 9582867Sdfr{ 9682867Sdfr u_int caplen = h->caplen; 9782867Sdfr int hdrlen; 9882867Sdfr u_int16_t fc; 9982867Sdfr u_int8_t seq; 10082867Sdfr 10182867Sdfr if (caplen < 3) { 10282867Sdfr ND_PRINT((ndo, "[|802.15.4] %x", caplen)); 10382867Sdfr return caplen; 10482867Sdfr } 10582867Sdfr 10682867Sdfr fc = EXTRACT_LE_16BITS(p); 10782867Sdfr hdrlen = extract_header_length(fc); 10882867Sdfr 10982867Sdfr seq = EXTRACT_LE_8BITS(p + 2); 11082867Sdfr 11182867Sdfr p += 3; 11282867Sdfr caplen -= 3; 11382867Sdfr 11482867Sdfr ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7])); 11582867Sdfr if (vflag) 11682867Sdfr ND_PRINT((ndo,"seq %02x ", seq)); 11782867Sdfr if (hdrlen == -1) { 11882867Sdfr ND_PRINT((ndo,"malformed! ")); 11982867Sdfr return caplen; 12082867Sdfr } 12182867Sdfr 12282867Sdfr 12382867Sdfr if (!vflag) { 12482867Sdfr p+= hdrlen; 12582867Sdfr caplen -= hdrlen; 12682867Sdfr } else { 12782867Sdfr u_int16_t panid = 0; 12882867Sdfr 12982867Sdfr switch ((fc >> 10) & 0x3) { 13082867Sdfr case 0x00: 13182867Sdfr ND_PRINT((ndo,"none ")); 13282867Sdfr break; 13382867Sdfr case 0x01: 13482867Sdfr ND_PRINT((ndo,"reserved destination addressing mode")); 13582867Sdfr return 0; 13682867Sdfr case 0x02: 13782867Sdfr panid = EXTRACT_LE_16BITS(p); 13882867Sdfr p += 2; 13982867Sdfr ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 14082867Sdfr p += 2; 14182867Sdfr break; 14282867Sdfr case 0x03: 14382867Sdfr panid = EXTRACT_LE_16BITS(p); 14482867Sdfr p += 2; 14582867Sdfr ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p))); 14682867Sdfr p += 8; 14782867Sdfr break; 14882867Sdfr } 14982867Sdfr ND_PRINT((ndo,"< "); 15082867Sdfr 15182867Sdfr switch ((fc >> 14) & 0x3) { 15282867Sdfr case 0x00: 15382867Sdfr ND_PRINT((ndo,"none ")); 15482867Sdfr break; 15582867Sdfr case 0x01: 15682867Sdfr ND_PRINT((ndo,"reserved source addressing mode")); 15782867Sdfr return 0; 15882867Sdfr case 0x02: 15982867Sdfr if (!(fc & (1 << 6))) { 16082867Sdfr panid = EXTRACT_LE_16BITS(p); 16182867Sdfr p += 2; 16282867Sdfr } 16382867Sdfr ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 16482867Sdfr p += 2; 16582867Sdfr break; 16682867Sdfr case 0x03: 16782867Sdfr if (!(fc & (1 << 6))) { 16882867Sdfr panid = EXTRACT_LE_16BITS(p); 16982867Sdfr p += 2; 17082867Sdfr } 17182867Sdfr ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p)))); 17282867Sdfr p += 8; 17382867Sdfr break; 17482867Sdfr } 17582867Sdfr 17682867Sdfr caplen -= hdrlen; 17782867Sdfr } 17882867Sdfr 17982867Sdfr if (!suppress_default_print) 18082867Sdfr (ndo->ndo_default_print)(ndo, p, caplen); 18182867Sdfr 18282867Sdfr return 0; 18382867Sdfr} 18482867Sdfr