]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-802_15_4.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304460, and update
[FreeBSD/FreeBSD.git] / contrib / 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 /* \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 }