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