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