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