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