xref: /netbsd-src/external/bsd/tcpdump/dist/print-geonet.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
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
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
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
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
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