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 #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
extract_header_length(uint16_t fc)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
ieee802_15_4_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)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