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