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