| /* |
| * 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; |
| } |