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", /* 4 */ 42 "Reserved", /* 5 */ 43 "Reserved", /* 6 */ 44 "Reserved", /* 7 */ 45 }; 46 47 static int 48 extract_header_length(uint16_t fc) 49 { 50 int len = 0; 51 52 switch ((fc >> 10) & 0x3) { 53 case 0x00: 54 if (fc & (1 << 6)) /* intra-PAN with none dest addr */ 55 return -1; 56 break; 57 case 0x01: 58 return -1; 59 case 0x02: 60 len += 4; 61 break; 62 case 0x03: 63 len += 10; 64 break; 65 } 66 67 switch ((fc >> 14) & 0x3) { 68 case 0x00: 69 break; 70 case 0x01: 71 return -1; 72 case 0x02: 73 len += 4; 74 break; 75 case 0x03: 76 len += 10; 77 break; 78 } 79 80 if (fc & (1 << 6)) { 81 if (len < 2) 82 return -1; 83 len -= 2; 84 } 85 86 return len; 87 } 88 89 90 u_int 91 ieee802_15_4_if_print(netdissect_options *ndo, 92 const struct pcap_pkthdr *h, const u_char *p) 93 { 94 u_int caplen = h->caplen; 95 int hdrlen; 96 uint16_t fc; 97 uint8_t seq; 98 99 if (caplen < 3) { 100 ND_PRINT((ndo, "[|802.15.4] %x", caplen)); 101 return caplen; 102 } 103 104 fc = EXTRACT_LE_16BITS(p); 105 hdrlen = extract_header_length(fc); 106 107 seq = EXTRACT_LE_8BITS(p + 2); 108 109 p += 3; 110 caplen -= 3; 111 112 ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7])); 113 if (ndo->ndo_vflag) 114 ND_PRINT((ndo,"seq %02x ", seq)); 115 if (hdrlen == -1) { 116 ND_PRINT((ndo,"invalid! ")); 117 return caplen; 118 } 119 120 121 if (!ndo->ndo_vflag) { 122 p+= hdrlen; 123 caplen -= hdrlen; 124 } else { 125 uint16_t panid = 0; 126 127 switch ((fc >> 10) & 0x3) { 128 case 0x00: 129 ND_PRINT((ndo,"none ")); 130 break; 131 case 0x01: 132 ND_PRINT((ndo,"reserved destination addressing mode")); 133 return 0; 134 case 0x02: 135 panid = EXTRACT_LE_16BITS(p); 136 p += 2; 137 ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 138 p += 2; 139 break; 140 case 0x03: 141 panid = EXTRACT_LE_16BITS(p); 142 p += 2; 143 ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); 144 p += 8; 145 break; 146 } 147 ND_PRINT((ndo,"< ")); 148 149 switch ((fc >> 14) & 0x3) { 150 case 0x00: 151 ND_PRINT((ndo,"none ")); 152 break; 153 case 0x01: 154 ND_PRINT((ndo,"reserved source addressing mode")); 155 return 0; 156 case 0x02: 157 if (!(fc & (1 << 6))) { 158 panid = EXTRACT_LE_16BITS(p); 159 p += 2; 160 } 161 ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); 162 p += 2; 163 break; 164 case 0x03: 165 if (!(fc & (1 << 6))) { 166 panid = EXTRACT_LE_16BITS(p); 167 p += 2; 168 } 169 ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); 170 p += 8; 171 break; 172 } 173 174 caplen -= hdrlen; 175 } 176 177 if (!ndo->ndo_suppress_default_print) 178 ND_DEFAULTPRINT(p, caplen); 179 180 return 0; 181 } 182