/* * Copyright (c) 2009 * Siemens AG, All rights reserved. * Dmitry Eremin-Solenikov (dbaryshkov@gmail.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <tcpdump-stdinc.h> #include <stdio.h> #include <pcap.h> #include <string.h> #include "interface.h" #include "addrtoname.h" #include "extract.h" static const char *ftypes[] = { "Beacon", /* 0 */ "Data", /* 1 */ "ACK", /* 2 */ "Command", /* 3 */ "Reserved", /* 4 */ "Reserved", /* 5 */ "Reserved", /* 6 */ "Reserved", /* 7 */ }; static int extract_header_length(u_int16_t fc) { int len = 0; switch ((fc >> 10) & 0x3) { case 0x00: if (fc & (1 << 6)) /* intra-PAN with none dest addr */ return -1; break; case 0x01: return -1; case 0x02: len += 4; break; case 0x03: len += 10; break; } switch ((fc >> 14) & 0x3) { case 0x00: break; case 0x01: return -1; case 0x02: len += 4; break; case 0x03: len += 10; break; } if (fc & (1 << 6)) { if (len < 2) return -1; len -= 2; } return len; } u_int ieee802_15_4_if_print(struct netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; int hdrlen; u_int16_t fc; u_int8_t seq; if (caplen < 3) { ND_PRINT((ndo, "[|802.15.4] %x", caplen)); return caplen; } fc = EXTRACT_LE_16BITS(p); hdrlen = extract_header_length(fc); seq = EXTRACT_LE_8BITS(p + 2); p += 3; caplen -= 3; ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7])); if (vflag) ND_PRINT((ndo,"seq %02x ", seq)); if (hdrlen == -1) { ND_PRINT((ndo,"malformed! ")); return caplen; } if (!vflag) { p+= hdrlen; caplen -= hdrlen; } else { u_int16_t panid = 0; switch ((fc >> 10) & 0x3) { case 0x00: ND_PRINT((ndo,"none ")); break; case 0x01: ND_PRINT((ndo,"reserved destination addressing mode")); return 0; case 0x02: panid = EXTRACT_LE_16BITS(p); p += 2; ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); p += 2; break; case 0x03: panid = EXTRACT_LE_16BITS(p); p += 2; ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p))); p += 8; break; } ND_PRINT((ndo,"< "); switch ((fc >> 14) & 0x3) { case 0x00: ND_PRINT((ndo,"none ")); break; case 0x01: ND_PRINT((ndo,"reserved source addressing mode")); return 0; case 0x02: if (!(fc & (1 << 6))) { panid = EXTRACT_LE_16BITS(p); p += 2; } ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); p += 2; break; case 0x03: if (!(fc & (1 << 6))) { panid = EXTRACT_LE_16BITS(p); p += 2; } ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p)))); p += 8; break; } caplen -= hdrlen; } if (!suppress_default_print) (ndo->ndo_default_print)(ndo, p, caplen); return 0; }