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