]> The Tcpdump Group git mirrors - tcpdump/blob - print-geonet.c
Printers must include 'netdissect.h', not 'interface.h'
[tcpdump] / print-geonet.c
1 /*
2 * Copyright (c) 2013 The TCPDUMP project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that: (1) source code
6 * distributions retain the above copyright notice and this paragraph
7 * in its entirety, and (2) distributions including binary code include
8 * the above copyright notice and this paragraph in its entirety in
9 * the documentation or other materials provided with the distribution.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
14 *
15 * Original code by Ola Martin Lykkja (ola.lykkja@q-free.com)
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <tcpdump-stdinc.h>
23
24 #include "netdissect.h"
25 #include "extract.h"
26 #include "addrtoname.h"
27
28
29 /*
30 ETSI TS 102 636-5-1 V1.1.1 (2011-02)
31 Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking;
32 Part 5: Transport Protocols; Sub-part 1: Basic Transport Protocol
33
34 ETSI TS 102 636-4-1 V1.1.1 (2011-06)
35 Intelligent Transport Systems (ITS); Vehicular communications; GeoNetworking;
36 Part 4: Geographical addressing and forwarding for point-to-point and point-to-multipoint communications;
37 Sub-part 1: Media-Independent Functionality
38 */
39
40 #define GEONET_ADDR_LEN 8
41
42 static const struct tok msg_type_values[] = {
43 { 0, "CAM" },
44 { 1, "DENM" },
45 { 101, "TPEGM" },
46 { 102, "TSPDM" },
47 { 103, "VPM" },
48 { 104, "SRM" },
49 { 105, "SLAM" },
50 { 106, "ecoCAM" },
51 { 107, "ITM" },
52 { 150, "SA" },
53 { 0, NULL }
54 };
55
56 static void
57 print_btp_body(netdissect_options *ndo,
58 const u_char *bp)
59 {
60 int version;
61 int msg_type;
62 const char *msg_type_str;
63
64 /* Assuming ItsDpuHeader */
65 version = bp[0];
66 msg_type = bp[1];
67 msg_type_str = tok2str(msg_type_values, "unknown (%u)", msg_type);
68
69 ND_PRINT((ndo, "; ItsPduHeader v:%d t:%d-%s", version, msg_type, msg_type_str));
70 }
71
72 static void
73 print_btp(netdissect_options *ndo,
74 const u_char *bp)
75 {
76 uint16_t dest = EXTRACT_16BITS(bp+0);
77 uint16_t src = EXTRACT_16BITS(bp+2);
78 ND_PRINT((ndo, "; BTP Dst:%u Src:%u", dest, src));
79 }
80
81 static int
82 print_long_pos_vector(netdissect_options *ndo,
83 const u_char *bp)
84 {
85 uint32_t lat, lon;
86
87 ND_PRINT((ndo, "GN_ADDR:%s ", linkaddr_string (ndo, bp, 0, GEONET_ADDR_LEN)));
88
89 if (!ND_TTEST2(*(bp+12), 8))
90 return (-1);
91 lat = EXTRACT_32BITS(bp+12);
92 ND_PRINT((ndo, "lat:%d ", lat));
93 lon = EXTRACT_32BITS(bp+16);
94 ND_PRINT((ndo, "lon:%d", lon));
95 return (0);
96 }
97
98
99 /*
100 * This is the top level routine of the printer. 'p' points
101 * to the geonet header of the packet.
102 */
103 void
104 geonet_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int length)
105 {
106 int version;
107 int next_hdr;
108 int hdr_type;
109 int hdr_subtype;
110 uint16_t payload_length;
111 int hop_limit;
112 const char *next_hdr_txt = "Unknown";
113 const char *hdr_type_txt = "Unknown";
114 int hdr_size = -1;
115
116 ND_PRINT((ndo, "GeoNet src:%s; ", etheraddr_string(ndo, eth+6)));
117
118 /* Process Common Header */
119 if (length < 36)
120 goto malformed;
121
122 ND_TCHECK2(*bp, 7);
123 version = bp[0] >> 4;
124 next_hdr = bp[0] & 0x0f;
125 hdr_type = bp[1] >> 4;
126 hdr_subtype = bp[1] & 0x0f;
127 payload_length = EXTRACT_16BITS(bp+4);
128 hop_limit = bp[7];
129
130 switch (next_hdr) {
131 case 0: next_hdr_txt = "Any"; break;
132 case 1: next_hdr_txt = "BTP-A"; break;
133 case 2: next_hdr_txt = "BTP-B"; break;
134 case 3: next_hdr_txt = "IPv6"; break;
135 }
136
137 switch (hdr_type) {
138 case 0: hdr_type_txt = "Any"; break;
139 case 1: hdr_type_txt = "Beacon"; break;
140 case 2: hdr_type_txt = "GeoUnicast"; break;
141 case 3: switch (hdr_subtype) {
142 case 0: hdr_type_txt = "GeoAnycastCircle"; break;
143 case 1: hdr_type_txt = "GeoAnycastRect"; break;
144 case 2: hdr_type_txt = "GeoAnycastElipse"; break;
145 }
146 break;
147 case 4: switch (hdr_subtype) {
148 case 0: hdr_type_txt = "GeoBroadcastCircle"; break;
149 case 1: hdr_type_txt = "GeoBroadcastRect"; break;
150 case 2: hdr_type_txt = "GeoBroadcastElipse"; break;
151 }
152 break;
153 case 5: switch (hdr_subtype) {
154 case 0: hdr_type_txt = "TopoScopeBcast-SH"; break;
155 case 1: hdr_type_txt = "TopoScopeBcast-MH"; break;
156 }
157 break;
158 case 6: switch (hdr_subtype) {
159 case 0: hdr_type_txt = "LocService-Request"; break;
160 case 1: hdr_type_txt = "LocService-Reply"; break;
161 }
162 break;
163 }
164
165 ND_PRINT((ndo, "v:%d ", version));
166 ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt));
167 ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt));
168 ND_PRINT((ndo, "HopLim:%d ", hop_limit));
169 ND_PRINT((ndo, "Payload:%d ", payload_length));
170 if (print_long_pos_vector(ndo, bp + 8) == -1)
171 goto trunc;
172
173 /* Skip Common Header */
174 length -= 36;
175 bp += 36;
176
177 /* Process Extended Headers */
178 switch (hdr_type) {
179 case 0: /* Any */
180 hdr_size = 0;
181 break;
182 case 1: /* Beacon */
183 hdr_size = 0;
184 break;
185 case 2: /* GeoUnicast */
186 break;
187 case 3: switch (hdr_subtype) {
188 case 0: /* GeoAnycastCircle */
189 break;
190 case 1: /* GeoAnycastRect */
191 break;
192 case 2: /* GeoAnycastElipse */
193 break;
194 }
195 break;
196 case 4: switch (hdr_subtype) {
197 case 0: /* GeoBroadcastCircle */
198 break;
199 case 1: /* GeoBroadcastRect */
200 break;
201 case 2: /* GeoBroadcastElipse */
202 break;
203 }
204 break;
205 case 5: switch (hdr_subtype) {
206 case 0: /* TopoScopeBcast-SH */
207 hdr_size = 0;
208 break;
209 case 1: /* TopoScopeBcast-MH */
210 hdr_size = 68 - 36;
211 break;
212 }
213 break;
214 case 6: switch (hdr_subtype) {
215 case 0: /* LocService-Request */
216 break;
217 case 1: /* LocService-Reply */
218 break;
219 }
220 break;
221 }
222
223 /* Skip Extended headers */
224 if (hdr_size >= 0) {
225 if (length < (u_int)hdr_size)
226 goto malformed;
227 ND_TCHECK2(*bp, hdr_size);
228 length -= hdr_size;
229 bp += hdr_size;
230 switch (next_hdr) {
231 case 0: /* Any */
232 break;
233 case 1:
234 case 2: /* BTP A/B */
235 if (length < 4)
236 goto malformed;
237 ND_TCHECK2(*bp, 4);
238 print_btp(ndo, bp);
239 length -= 4;
240 bp += 4;
241 if (length >= 2) {
242 /*
243 * XXX - did print_btp_body()
244 * return if length < 2
245 * because this is optional,
246 * or was that just not
247 * reporting genuine errors?
248 */
249 ND_TCHECK2(*bp, 2);
250 print_btp_body(ndo, bp);
251 }
252 break;
253 case 3: /* IPv6 */
254 break;
255 }
256 }
257
258 /* Print user data part */
259 if (ndo->ndo_vflag)
260 ND_DEFAULTPRINT(bp, length);
261 return;
262
263 malformed:
264 ND_PRINT((ndo, " Malformed (small) "));
265 /* XXX - print the remaining data as hex? */
266 return;
267
268 trunc:
269 ND_PRINT((ndo, "[|geonet]"));
270 }
271
272
273 /*
274 * Local Variables:
275 * c-style: whitesmith
276 * c-basic-offset: 8
277 * End:
278 */