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