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#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <tcpdump-stdinc.h>
23
24#include <pcap.h>
25#include <stdio.h>
26#include <string.h>
27
28#include "interface.h"
29#include "extract.h"
30#include "addrtoname.h"
31
32
33/*
34   ETSI TS 102 636-5-1 V1.1.1 (2011-02)
35   Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking;
36   Part 5: Transport Protocols; Sub-part 1: Basic Transport Protocol
37
38   ETSI TS 102 636-4-1 V1.1.1 (2011-06)
39   Intelligent Transport Systems (ITS); Vehicular communications; GeoNetworking;
40   Part 4: Geographical addressing and forwarding for point-to-point and point-to-multipoint communications;
41   Sub-part 1: Media-Independent Functionality
42*/
43
44static const struct tok msg_type_values[] = {
45	{   0, "CAM" },
46	{   1, "DENM" },
47	{ 101, "TPEGM" },
48	{ 102, "TSPDM" },
49	{ 103, "VPM" },
50	{ 104, "SRM" },
51	{ 105, "SLAM" },
52	{ 106, "ecoCAM" },
53	{ 107, "ITM" },
54	{ 150, "SA" },
55	{   0, NULL }
56};
57
58static void
59print_btp_body(const u_char *bp, u_int length)
60{
61	int version;
62	int msg_type;
63	const char *msg_type_str;
64
65	if (length <= 2) {
66		return;
67	}
68
69	/* Assuming ItsDpuHeader */
70	version = bp[0];
71	msg_type = bp[1];
72	msg_type_str = tok2str(msg_type_values, "unknown (%u)", msg_type);
73
74	printf("; ItsPduHeader v:%d t:%d-%s", version, msg_type, msg_type_str);
75}
76
77static void
78print_btp(const u_char *bp)
79{
80	u_int16_t dest = EXTRACT_16BITS(bp+0);
81	u_int16_t src = EXTRACT_16BITS(bp+2);
82	printf("; BTP Dst:%u Src:%u", dest, src);
83}
84
85static void
86print_long_pos_vector(const u_char *bp)
87{
88	int i;
89	u_int32_t lat, lon;
90
91	printf("GN_ADDR:");
92	for (i=0; i<8; i++) {
93		if (i) printf(":");
94		printf("%02x", bp[i]);
95	}
96	printf(" ");
97
98	lat = EXTRACT_32BITS(bp+12);
99	printf("lat:%d ", lat);
100	lon = EXTRACT_32BITS(bp+16);
101	printf("lon:%d", lon);
102}
103
104
105/*
106 * This is the top level routine of the printer.  'p' points
107 * to the geonet header of the packet.
108 */
109void
110geonet_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int length)
111{
112	printf("GeoNet src:%s; ", etheraddr_string(eth+6));
113
114	if (length >= 36) {
115		/* Process Common Header */
116		int version = bp[0] >> 4;
117		int next_hdr = bp[0] & 0x0f;
118		int hdr_type = bp[1] >> 4;
119		int hdr_subtype = bp[1] & 0x0f;
120		u_int16_t payload_length = EXTRACT_16BITS(bp+4);
121		int hop_limit = bp[7];
122		const char *next_hdr_txt = "Unknown";
123		const char *hdr_type_txt = "Unknown";
124		int hdr_size = -1;
125
126		switch (next_hdr) {
127			case 0: next_hdr_txt = "Any"; break;
128			case 1: next_hdr_txt = "BTP-A"; break;
129			case 2: next_hdr_txt = "BTP-B"; break;
130			case 3: next_hdr_txt = "IPv6"; break;
131		}
132
133		switch (hdr_type) {
134			case 0: hdr_type_txt = "Any"; break;
135			case 1: hdr_type_txt = "Beacon"; break;
136			case 2: hdr_type_txt = "GeoUnicast"; break;
137			case 3: switch (hdr_subtype) {
138					case 0: hdr_type_txt = "GeoAnycastCircle"; break;
139					case 1: hdr_type_txt = "GeoAnycastRect"; break;
140					case 2: hdr_type_txt = "GeoAnycastElipse"; break;
141				}
142				break;
143			case 4: switch (hdr_subtype) {
144					case 0: hdr_type_txt = "GeoBroadcastCircle"; break;
145					case 1: hdr_type_txt = "GeoBroadcastRect"; break;
146					case 2: hdr_type_txt = "GeoBroadcastElipse"; break;
147				}
148				break;
149			case 5: switch (hdr_subtype) {
150					case 0: hdr_type_txt = "TopoScopeBcast-SH"; break;
151					case 1: hdr_type_txt = "TopoScopeBcast-MH"; break;
152				}
153				break;
154			case 6: switch (hdr_subtype) {
155					case 0: hdr_type_txt = "LocService-Request"; break;
156					case 1: hdr_type_txt = "LocService-Reply"; break;
157				}
158				break;
159		}
160
161		printf("v:%d ", version);
162		printf("NH:%d-%s ", next_hdr, next_hdr_txt);
163		printf("HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt);
164		printf("HopLim:%d ", hop_limit);
165		printf("Payload:%d ", payload_length);
166        	print_long_pos_vector(bp + 8);
167
168		/* Skip Common Header */
169		length -= 36;
170		bp += 36;
171
172		/* Process Extended Headers */
173		switch (hdr_type) {
174			case 0: /* Any */
175				hdr_size = 0;
176				break;
177			case 1: /* Beacon */
178				hdr_size = 0;
179				break;
180			case 2: /* GeoUnicast */
181				break;
182			case 3: switch (hdr_subtype) {
183					case 0: /* GeoAnycastCircle */
184						break;
185					case 1: /* GeoAnycastRect */
186						break;
187					case 2: /* GeoAnycastElipse */
188						break;
189				}
190				break;
191			case 4: switch (hdr_subtype) {
192					case 0: /* GeoBroadcastCircle */
193						break;
194					case 1: /* GeoBroadcastRect */
195						break;
196					case 2: /* GeoBroadcastElipse */
197						break;
198				}
199				break;
200			case 5: switch (hdr_subtype) {
201					case 0: /* TopoScopeBcast-SH */
202						hdr_size = 0;
203						break;
204					case 1: /* TopoScopeBcast-MH */
205						hdr_size = 68 - 36;
206						break;
207				}
208				break;
209			case 6: switch (hdr_subtype) {
210					case 0: /* LocService-Request */
211						break;
212					case 1: /* LocService-Reply */
213						break;
214				}
215				break;
216		}
217
218		/* Skip Extended headers */
219		if (hdr_size >= 0) {
220			length -= hdr_size;
221			bp += hdr_size;
222			switch (next_hdr) {
223				case 0: /* Any */
224					break;
225				case 1:
226				case 2: /* BTP A/B */
227					print_btp(bp);
228					length -= 4;
229					bp += 4;
230					print_btp_body(bp, length);
231					break;
232				case 3: /* IPv6 */
233					break;
234			}
235		}
236	} else {
237		printf("Malformed (small) ");
238	}
239
240	/* Print user data part */
241	if (ndo->ndo_vflag)
242		default_print(bp, length);
243}
244
245
246/*
247 * Local Variables:
248 * c-style: whitesmith
249 * c-basic-offset: 8
250 * End:
251 */
252