1 /* 2 * Copyright (c) 2009 3 * Siemens AG, All rights reserved. 4 * Dmitry Eremin-Solenikov (dbaryshkov@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 /* \summary: IEEE 802.15.4 printer */ 24 25 #ifdef HAVE_CONFIG_H 26 #include "config.h" 27 #endif 28 29 #include <netdissect-stdinc.h> 30 31 #include "netdissect.h" 32 #include "addrtoname.h" 33 34 #include "extract.h" 35 36 static const char *ftypes[] = { 37 "Beacon", /* 0 */ 38 "Data", /* 1 */ 39 "ACK", /* 2 */ 40 "Command", /* 3 */ 41 "Reserved (0x4)", /* 4 */ 42 "Reserved (0x5)", /* 5 */ 43 "Reserved (0x6)", /* 6 */ 44 "Reserved (0x7)", /* 7 */ 45 }; 46 47 /* 48 * Frame Control subfields. 49 */ 50 #define FC_FRAME_TYPE(fc) ((fc) & 0x7) 51 #define FC_SECURITY_ENABLED 0x0008 52 #define FC_FRAME_PENDING 0x0010 53 #define FC_ACK_REQUEST 0x0020 54 #define FC_PAN_ID_COMPRESSION 0x0040 55 #define FC_DEST_ADDRESSING_MODE(fc) (((fc) >> 10) & 0x3) 56 #define FC_FRAME_VERSION(fc) (((fc) >> 12) & 0x3) 57 #define FC_SRC_ADDRESSING_MODE(fc) (((fc) >> 14) & 0x3) 58 59 #define FC_ADDRESSING_MODE_NONE 0x00 60 #define FC_ADDRESSING_MODE_RESERVED 0x01 61 #define FC_ADDRESSING_MODE_SHORT 0x02 62 #define FC_ADDRESSING_MODE_LONG 0x03 63 64 u_int 65 ieee802_15_4_if_print(netdissect_options *ndo, 66 const struct pcap_pkthdr *h, const u_char *p) 67 { 68 u_int caplen = h->caplen; 69 u_int hdrlen; 70 uint16_t fc; 71 uint8_t seq; 72 uint16_t panid = 0; 73 74 if (caplen < 3) { 75 ND_PRINT((ndo, "[|802.15.4]")); 76 return caplen; 77 } 78 hdrlen = 3; 79 80 fc = EXTRACT_LE_16BITS(p); 81 seq = EXTRACT_LE_8BITS(p + 2); 82 83 p += 3; 84 caplen -= 3; 85 86 ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[FC_FRAME_TYPE(fc)])); 87 if (ndo->ndo_vflag) 88 ND_PRINT((ndo,"seq %02x ", seq)); 89 90 /* 91 * Destination address and PAN ID, if present. 92 */ 93 switch (FC_DEST_ADDRESSING_MODE(fc)) { 94 case FC_ADDRESSING_MODE_NONE: 95 if (fc & FC_PAN_ID_COMPRESSION) { 96 /* 97 * PAN ID compression; this requires that both 98 * the source and destination addresses be present, 99 * but the destination address is missing. 100 */ 101 ND_PRINT((ndo, "[|802.15.4]")); 102 return hdrlen; 103 } 104 if (ndo->ndo_vflag) 105 ND_PRINT((ndo,"none ")); 106 break; 107 case FC_ADDRESSING_MODE_RESERVED: 108 if (ndo->ndo_vflag) 109 ND_PRINT((ndo,"reserved destination addressing mode")); 110 return hdrlen; 111 case FC_ADDRESSING_MODE_SHORT: 112 if (caplen < 2) { 113 ND_PRINT((ndo, "[|802.15.4]")); 114 return hdrlen; 115 } 116 panid = EXTRACT_LE_16BITS(p); 117 p += 2; 118 caplen -= 2; 119 hdrlen += 2; 120 if (caplen < 2) { 121 ND_PRINT((ndo, "[|802.15.4]")); 122 return hdrlen; 123 } 124 if (ndo->ndo_vflag) 125 ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 126 p += 2; 127 caplen -= 2; 128 hdrlen += 2; 129 break; 130 case FC_ADDRESSING_MODE_LONG: 131 if (caplen < 2) { 132 ND_PRINT((ndo, "[|802.15.4]")); 133 return hdrlen; 134 } 135 panid = EXTRACT_LE_16BITS(p); 136 p += 2; 137 caplen -= 2; 138 hdrlen += 2; 139 if (caplen < 8) { 140 ND_PRINT((ndo, "[|802.15.4]")); 141 return hdrlen; 142 } 143 if (ndo->ndo_vflag) 144 ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); 145 p += 8; 146 caplen -= 8; 147 hdrlen += 8; 148 break; 149 } 150 if (ndo->ndo_vflag) 151 ND_PRINT((ndo,"< ")); 152 153 /* 154 * Source address and PAN ID, if present. 155 */ 156 switch (FC_SRC_ADDRESSING_MODE(fc)) { 157 case FC_ADDRESSING_MODE_NONE: 158 if (ndo->ndo_vflag) 159 ND_PRINT((ndo,"none ")); 160 break; 161 case FC_ADDRESSING_MODE_RESERVED: 162 if (ndo->ndo_vflag) 163 ND_PRINT((ndo,"reserved source addressing mode")); 164 return 0; 165 case FC_ADDRESSING_MODE_SHORT: 166 if (!(fc & FC_PAN_ID_COMPRESSION)) { 167 /* 168 * The source PAN ID is not compressed out, so 169 * fetch it. (Otherwise, we'll use the destination 170 * PAN ID, fetched above.) 171 */ 172 if (caplen < 2) { 173 ND_PRINT((ndo, "[|802.15.4]")); 174 return hdrlen; 175 } 176 panid = EXTRACT_LE_16BITS(p); 177 p += 2; 178 caplen -= 2; 179 hdrlen += 2; 180 } 181 if (caplen < 2) { 182 ND_PRINT((ndo, "[|802.15.4]")); 183 return hdrlen; 184 } 185 if (ndo->ndo_vflag) 186 ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 187 p += 2; 188 caplen -= 2; 189 hdrlen += 2; 190 break; 191 case FC_ADDRESSING_MODE_LONG: 192 if (!(fc & FC_PAN_ID_COMPRESSION)) { 193 /* 194 * The source PAN ID is not compressed out, so 195 * fetch it. (Otherwise, we'll use the destination 196 * PAN ID, fetched above.) 197 */ 198 if (caplen < 2) { 199 ND_PRINT((ndo, "[|802.15.4]")); 200 return hdrlen; 201 } 202 panid = EXTRACT_LE_16BITS(p); 203 p += 2; 204 caplen -= 2; 205 hdrlen += 2; 206 } 207 if (caplen < 8) { 208 ND_PRINT((ndo, "[|802.15.4]")); 209 return hdrlen; 210 } 211 if (ndo->ndo_vflag) 212 ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); 213 p += 8; 214 caplen -= 8; 215 hdrlen += 8; 216 break; 217 } 218 219 if (!ndo->ndo_suppress_default_print) 220 ND_DEFAULTPRINT(p, caplen); 221 222 return hdrlen; 223 } 224