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