]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-802_15_4.c
Update mandoc to 20160116
[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 #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
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
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 }