1 /* 2 * Copyright (c) 2009 3 * Siemens AG, All rights reserved. 4 * Dmitry Eremin-Solenikov (dbaryshkov (at) gmail.com) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that: (1) source code distributions 8 * retain the above copyright notice and this paragraph in its entirety, (2) 9 * distributions including binary code include the above copyright notice and 10 * this paragraph in its entirety in the documentation or other materials 11 * provided with the distribution, and (3) all advertising materials mentioning 12 * features or use of this software display the following acknowledgement: 13 * ``This product includes software developed by the University of California, 14 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 15 * the University nor the names of its contributors may be used to endorse 16 * or promote products derived from this software without specific prior 17 * written permission. 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 21 */ 22 23 #define NETDISSECT_REWORKED 24 #ifdef HAVE_CONFIG_H 25 #include "config.h" 26 #endif 27 28 #include <tcpdump-stdinc.h> 29 30 #include "interface.h" 31 #include "addrtoname.h" 32 33 #include "extract.h" 34 35 static const char *ftypes[] = { 36 "Beacon", /* 0 */ 37 "Data", /* 1 */ 38 "ACK", /* 2 */ 39 "Command", /* 3 */ 40 "Reserved", /* 4 */ 41 "Reserved", /* 5 */ 42 "Reserved", /* 6 */ 43 "Reserved", /* 7 */ 44 }; 45 46 static int 47 extract_header_length(uint16_t fc) 48 { 49 int len = 0; 50 51 switch ((fc >> 10) & 0x3) { 52 case 0x00: 53 if (fc & (1 << 6)) /* intra-PAN with none dest addr */ 54 return -1; 55 break; 56 case 0x01: 57 return -1; 58 case 0x02: 59 len += 4; 60 break; 61 case 0x03: 62 len += 10; 63 break; 64 } 65 66 switch ((fc >> 14) & 0x3) { 67 case 0x00: 68 break; 69 case 0x01: 70 return -1; 71 case 0x02: 72 len += 4; 73 break; 74 case 0x03: 75 len += 10; 76 break; 77 } 78 79 if (fc & (1 << 6)) { 80 if (len < 2) 81 return -1; 82 len -= 2; 83 } 84 85 return len; 86 } 87 88 89 u_int 90 ieee802_15_4_if_print(netdissect_options *ndo, 91 const struct pcap_pkthdr *h, const u_char *p) 92 { 93 u_int caplen = h->caplen; 94 int hdrlen; 95 uint16_t fc; 96 uint8_t seq; 97 98 if (caplen < 3) { 99 ND_PRINT((ndo, "[|802.15.4] %x", caplen)); 100 return caplen; 101 } 102 103 fc = EXTRACT_LE_16BITS(p); 104 hdrlen = extract_header_length(fc); 105 106 seq = EXTRACT_LE_8BITS(p + 2); 107 108 p += 3; 109 caplen -= 3; 110 111 ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7])); 112 if (ndo->ndo_vflag) 113 ND_PRINT((ndo,"seq %02x ", seq)); 114 if (hdrlen == -1) { 115 ND_PRINT((ndo,"malformed! ")); 116 return caplen; 117 } 118 119 120 if (!ndo->ndo_vflag) { 121 p+= hdrlen; 122 caplen -= hdrlen; 123 } else { 124 uint16_t panid = 0; 125 126 switch ((fc >> 10) & 0x3) { 127 case 0x00: 128 ND_PRINT((ndo,"none ")); 129 break; 130 case 0x01: 131 ND_PRINT((ndo,"reserved destination addressing mode")); 132 return 0; 133 case 0x02: 134 panid = EXTRACT_LE_16BITS(p); 135 p += 2; 136 ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 137 p += 2; 138 break; 139 case 0x03: 140 panid = EXTRACT_LE_16BITS(p); 141 p += 2; 142 ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p))); 143 p += 8; 144 break; 145 } 146 ND_PRINT((ndo,"< ")); 147 148 switch ((fc >> 14) & 0x3) { 149 case 0x00: 150 ND_PRINT((ndo,"none ")); 151 break; 152 case 0x01: 153 ND_PRINT((ndo,"reserved source addressing mode")); 154 return 0; 155 case 0x02: 156 if (!(fc & (1 << 6))) { 157 panid = EXTRACT_LE_16BITS(p); 158 p += 2; 159 } 160 ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 161 p += 2; 162 break; 163 case 0x03: 164 if (!(fc & (1 << 6))) { 165 panid = EXTRACT_LE_16BITS(p); 166 p += 2; 167 } 168 ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p))); 169 p += 8; 170 break; 171 } 172 173 caplen -= hdrlen; 174 } 175 176 if (!ndo->ndo_suppress_default_print) 177 ND_DEFAULTPRINT(p, caplen); 178 179 return 0; 180 } 181