xref: /netbsd-src/external/bsd/tcpdump/dist/print-geonet.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
1026d7285Schristos /*
2026d7285Schristos  * Copyright (c) 2013 The TCPDUMP project
3026d7285Schristos  *
4026d7285Schristos  * Redistribution and use in source and binary forms, with or without
5026d7285Schristos  * modification, are permitted provided that: (1) source code
6026d7285Schristos  * distributions retain the above copyright notice and this paragraph
7026d7285Schristos  * in its entirety, and (2) distributions including binary code include
8026d7285Schristos  * the above copyright notice and this paragraph in its entirety in
9026d7285Schristos  * the documentation or other materials provided with the distribution.
10026d7285Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11026d7285Schristos  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12026d7285Schristos  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13026d7285Schristos  * FOR A PARTICULAR PURPOSE.
14026d7285Schristos  *
15026d7285Schristos  * Original code by Ola Martin Lykkja (ola.lykkja@q-free.com)
16026d7285Schristos  */
17026d7285Schristos 
18fdccd7e4Schristos #include <sys/cdefs.h>
19fdccd7e4Schristos #ifndef lint
20*26ba0b50Schristos __RCSID("$NetBSD: print-geonet.c,v 1.5 2024/09/02 16:15:31 christos Exp $");
21fdccd7e4Schristos #endif
22fdccd7e4Schristos 
23dc860a36Sspz /* \summary: ISO CALM FAST and ETSI GeoNetworking printer */
24dc860a36Sspz 
25c74ad251Schristos #include <config.h>
26026d7285Schristos 
27c74ad251Schristos #include "netdissect-stdinc.h"
28026d7285Schristos 
29c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK
30784088dfSchristos #include "netdissect.h"
31026d7285Schristos #include "extract.h"
32026d7285Schristos #include "addrtoname.h"
33026d7285Schristos 
34026d7285Schristos 
35026d7285Schristos /*
36026d7285Schristos    ETSI TS 102 636-5-1 V1.1.1 (2011-02)
37026d7285Schristos    Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking;
38026d7285Schristos    Part 5: Transport Protocols; Sub-part 1: Basic Transport Protocol
39026d7285Schristos 
40026d7285Schristos    ETSI TS 102 636-4-1 V1.1.1 (2011-06)
41026d7285Schristos    Intelligent Transport Systems (ITS); Vehicular communications; GeoNetworking;
42026d7285Schristos    Part 4: Geographical addressing and forwarding for point-to-point and point-to-multipoint communications;
43026d7285Schristos    Sub-part 1: Media-Independent Functionality
44026d7285Schristos */
45026d7285Schristos 
46c47fd378Schristos #define GEONET_ADDR_LEN 8
47c47fd378Schristos 
48026d7285Schristos static const struct tok msg_type_values[] = {
49026d7285Schristos 	{   0, "CAM" },
50026d7285Schristos 	{   1, "DENM" },
51026d7285Schristos 	{ 101, "TPEGM" },
52026d7285Schristos 	{ 102, "TSPDM" },
53026d7285Schristos 	{ 103, "VPM" },
54026d7285Schristos 	{ 104, "SRM" },
55026d7285Schristos 	{ 105, "SLAM" },
56026d7285Schristos 	{ 106, "ecoCAM" },
57026d7285Schristos 	{ 107, "ITM" },
58026d7285Schristos 	{ 150, "SA" },
59026d7285Schristos 	{   0, NULL }
60026d7285Schristos };
61026d7285Schristos 
62026d7285Schristos static void
63c47fd378Schristos print_btp_body(netdissect_options *ndo,
643d25ea14Schristos 	       const u_char *bp)
65026d7285Schristos {
66c74ad251Schristos 	u_int msg_type;
67026d7285Schristos 
68c74ad251Schristos 	/* Assuming ItsPduHeader */
69c74ad251Schristos 	ND_PRINT("; ItsPduHeader v:%u", GET_U_1(bp));
70026d7285Schristos 
71c74ad251Schristos 	msg_type = GET_U_1(bp + 1);
72c74ad251Schristos 	ND_PRINT(" t:%u-%s", msg_type,
73c74ad251Schristos 	         tok2str(msg_type_values, "unknown (%u)", msg_type));
74026d7285Schristos }
75026d7285Schristos 
76c74ad251Schristos /* EN 302 636-5-1 V2.2.1 Section 7.2: BTP-A header */
77026d7285Schristos static void
78c47fd378Schristos print_btp(netdissect_options *ndo,
79c47fd378Schristos 	  const u_char *bp)
80026d7285Schristos {
81c74ad251Schristos 	ND_PRINT("; BTP Dst:%u", GET_BE_U_2(bp + 0));
82c74ad251Schristos 	ND_PRINT(" Src:%u", GET_BE_U_2(bp + 2));
83026d7285Schristos }
84026d7285Schristos 
85c74ad251Schristos static void
86c47fd378Schristos print_long_pos_vector(netdissect_options *ndo,
87c47fd378Schristos 		      const u_char *bp)
88026d7285Schristos {
89c74ad251Schristos 	ND_PRINT("GN_ADDR:%s ", GET_LINKADDR_STRING(bp, LINKADDR_OTHER, GEONET_ADDR_LEN));
90c74ad251Schristos 	ND_PRINT("lat:%u ", GET_BE_U_4(bp + 12));
91c74ad251Schristos 	ND_PRINT("lon:%u", GET_BE_U_4(bp + 16));
92026d7285Schristos }
93026d7285Schristos 
94026d7285Schristos 
95026d7285Schristos /*
96026d7285Schristos  * This is the top level routine of the printer.  'p' points
97026d7285Schristos  * to the geonet header of the packet.
98026d7285Schristos  */
99026d7285Schristos void
100dc860a36Sspz geonet_print(netdissect_options *ndo, const u_char *bp, u_int length,
101dc860a36Sspz 	     const struct lladdr_info *src)
102026d7285Schristos {
103c74ad251Schristos 	u_int version;
104c74ad251Schristos 	u_int next_hdr;
105c74ad251Schristos 	u_int hdr_type;
106c74ad251Schristos 	u_int hdr_subtype;
1073d25ea14Schristos 	uint16_t payload_length;
108c74ad251Schristos 	u_int hop_limit;
109026d7285Schristos 	const char *next_hdr_txt = "Unknown";
110026d7285Schristos 	const char *hdr_type_txt = "Unknown";
111026d7285Schristos 	int hdr_size = -1;
112026d7285Schristos 
113c74ad251Schristos 	ndo->ndo_protocol = "geonet";
114c74ad251Schristos 	ND_PRINT("GeoNet ");
115dc860a36Sspz 	if (src != NULL)
116c74ad251Schristos 		ND_PRINT("src:%s", (src->addr_string)(ndo, src->addr));
117c74ad251Schristos 	ND_PRINT("; ");
1183d25ea14Schristos 
1193d25ea14Schristos 	/* Process Common Header */
120c74ad251Schristos 	if (length < 36) {
121c74ad251Schristos 		ND_PRINT(" (common header length %u < 36)", length);
122784088dfSchristos 		goto invalid;
123c74ad251Schristos 	}
1243d25ea14Schristos 
125c74ad251Schristos 	version = GET_U_1(bp) >> 4;
126c74ad251Schristos 	next_hdr = GET_U_1(bp) & 0x0f;
127c74ad251Schristos 	hdr_type = GET_U_1(bp + 1) >> 4;
128c74ad251Schristos 	hdr_subtype = GET_U_1(bp + 1) & 0x0f;
129c74ad251Schristos 	payload_length = GET_BE_U_2(bp + 4);
130c74ad251Schristos 	hop_limit = GET_U_1(bp + 7);
1313d25ea14Schristos 
132026d7285Schristos 	switch (next_hdr) {
133026d7285Schristos 		case 0: next_hdr_txt = "Any"; break;
134026d7285Schristos 		case 1: next_hdr_txt = "BTP-A"; break;
135026d7285Schristos 		case 2: next_hdr_txt = "BTP-B"; break;
136026d7285Schristos 		case 3: next_hdr_txt = "IPv6"; break;
137026d7285Schristos 	}
138026d7285Schristos 
139026d7285Schristos 	switch (hdr_type) {
140026d7285Schristos 		case 0: hdr_type_txt = "Any"; break;
141026d7285Schristos 		case 1: hdr_type_txt = "Beacon"; break;
142026d7285Schristos 		case 2: hdr_type_txt = "GeoUnicast"; break;
143026d7285Schristos 		case 3: switch (hdr_subtype) {
144026d7285Schristos 				case 0: hdr_type_txt = "GeoAnycastCircle"; break;
145026d7285Schristos 				case 1: hdr_type_txt = "GeoAnycastRect"; break;
146026d7285Schristos 				case 2: hdr_type_txt = "GeoAnycastElipse"; break;
147026d7285Schristos 			}
148026d7285Schristos 			break;
149026d7285Schristos 		case 4: switch (hdr_subtype) {
150026d7285Schristos 				case 0: hdr_type_txt = "GeoBroadcastCircle"; break;
151026d7285Schristos 				case 1: hdr_type_txt = "GeoBroadcastRect"; break;
152026d7285Schristos 				case 2: hdr_type_txt = "GeoBroadcastElipse"; break;
153026d7285Schristos 			}
154026d7285Schristos 			break;
155026d7285Schristos 		case 5: switch (hdr_subtype) {
156026d7285Schristos 				case 0: hdr_type_txt = "TopoScopeBcast-SH"; break;
157026d7285Schristos 				case 1: hdr_type_txt = "TopoScopeBcast-MH"; break;
158026d7285Schristos 			}
159026d7285Schristos 			break;
160026d7285Schristos 		case 6: switch (hdr_subtype) {
161026d7285Schristos 				case 0: hdr_type_txt = "LocService-Request"; break;
162026d7285Schristos 				case 1: hdr_type_txt = "LocService-Reply"; break;
163026d7285Schristos 			}
164026d7285Schristos 			break;
165026d7285Schristos 	}
166026d7285Schristos 
167c74ad251Schristos 	ND_PRINT("v:%u ", version);
168c74ad251Schristos 	ND_PRINT("NH:%u-%s ", next_hdr, next_hdr_txt);
169c74ad251Schristos 	ND_PRINT("HT:%u-%u-%s ", hdr_type, hdr_subtype, hdr_type_txt);
170c74ad251Schristos 	ND_PRINT("HopLim:%u ", hop_limit);
171c74ad251Schristos 	ND_PRINT("Payload:%u ", payload_length);
172c74ad251Schristos 	print_long_pos_vector(ndo, bp + 8);
173026d7285Schristos 
174026d7285Schristos 	/* Skip Common Header */
175c74ad251Schristos 	ND_TCHECK_LEN(bp, 36);
176026d7285Schristos 	length -= 36;
177026d7285Schristos 	bp += 36;
178026d7285Schristos 
179026d7285Schristos 	/* Process Extended Headers */
180026d7285Schristos 	switch (hdr_type) {
181026d7285Schristos 		case 0: /* Any */
182026d7285Schristos 			hdr_size = 0;
183026d7285Schristos 			break;
184026d7285Schristos 		case 1: /* Beacon */
185026d7285Schristos 			hdr_size = 0;
186026d7285Schristos 			break;
187026d7285Schristos 		case 2: /* GeoUnicast */
188026d7285Schristos 			break;
189026d7285Schristos 		case 3: switch (hdr_subtype) {
190026d7285Schristos 				case 0: /* GeoAnycastCircle */
191026d7285Schristos 					break;
192026d7285Schristos 				case 1: /* GeoAnycastRect */
193026d7285Schristos 					break;
194026d7285Schristos 				case 2: /* GeoAnycastElipse */
195026d7285Schristos 					break;
196026d7285Schristos 			}
197026d7285Schristos 			break;
198026d7285Schristos 		case 4: switch (hdr_subtype) {
199026d7285Schristos 				case 0: /* GeoBroadcastCircle */
200026d7285Schristos 					break;
201026d7285Schristos 				case 1: /* GeoBroadcastRect */
202026d7285Schristos 					break;
203026d7285Schristos 				case 2: /* GeoBroadcastElipse */
204026d7285Schristos 					break;
205026d7285Schristos 			}
206026d7285Schristos 			break;
207026d7285Schristos 		case 5: switch (hdr_subtype) {
208026d7285Schristos 				case 0: /* TopoScopeBcast-SH */
209026d7285Schristos 					hdr_size = 0;
210026d7285Schristos 					break;
211026d7285Schristos 				case 1: /* TopoScopeBcast-MH */
212026d7285Schristos 					hdr_size = 68 - 36;
213026d7285Schristos 					break;
214026d7285Schristos 			}
215026d7285Schristos 			break;
216026d7285Schristos 		case 6: switch (hdr_subtype) {
217026d7285Schristos 				case 0: /* LocService-Request */
218026d7285Schristos 					break;
219026d7285Schristos 				case 1: /* LocService-Reply */
220026d7285Schristos 					break;
221026d7285Schristos 			}
222026d7285Schristos 			break;
223026d7285Schristos 	}
224026d7285Schristos 
225026d7285Schristos 	/* Skip Extended headers */
226026d7285Schristos 	if (hdr_size >= 0) {
227c74ad251Schristos 		if (length < (u_int)hdr_size) {
228c74ad251Schristos 			ND_PRINT(" (header size %d > %u)", hdr_size, length);
229784088dfSchristos 			goto invalid;
230c74ad251Schristos 		}
231c74ad251Schristos 		ND_TCHECK_LEN(bp, hdr_size);
232026d7285Schristos 		length -= hdr_size;
233026d7285Schristos 		bp += hdr_size;
234026d7285Schristos 		switch (next_hdr) {
235026d7285Schristos 			case 0: /* Any */
236026d7285Schristos 				break;
237026d7285Schristos 			case 1:
238026d7285Schristos 			case 2: /* BTP A/B */
239c74ad251Schristos 				if (length < 4) {
240c74ad251Schristos 					ND_PRINT(" (BTP length %u < 4)", length);
241784088dfSchristos 					goto invalid;
242c74ad251Schristos 				}
243c47fd378Schristos 				print_btp(ndo, bp);
244026d7285Schristos 				length -= 4;
245026d7285Schristos 				bp += 4;
2463d25ea14Schristos 				if (length >= 2) {
2473d25ea14Schristos 					/*
2483d25ea14Schristos 					 * XXX - did print_btp_body()
2493d25ea14Schristos 					 * return if length < 2
2503d25ea14Schristos 					 * because this is optional,
2513d25ea14Schristos 					 * or was that just not
2523d25ea14Schristos 					 * reporting genuine errors?
2533d25ea14Schristos 					 */
2543d25ea14Schristos 					print_btp_body(ndo, bp);
2553d25ea14Schristos 				}
256026d7285Schristos 				break;
257026d7285Schristos 			case 3: /* IPv6 */
258026d7285Schristos 				break;
259026d7285Schristos 		}
260026d7285Schristos 	}
261026d7285Schristos 
262026d7285Schristos 	/* Print user data part */
263026d7285Schristos 	if (ndo->ndo_vflag)
264c47fd378Schristos 		ND_DEFAULTPRINT(bp, length);
2653d25ea14Schristos 	return;
2663d25ea14Schristos 
267784088dfSchristos invalid:
268c74ad251Schristos 	nd_print_invalid(ndo);
2693d25ea14Schristos 	/* XXX - print the remaining data as hex? */
270026d7285Schristos }
271