13c602fabSXin LI /* 23c602fabSXin LI * Copyright (c) 2013 The TCPDUMP project 33c602fabSXin LI * 43c602fabSXin LI * Redistribution and use in source and binary forms, with or without 53c602fabSXin LI * modification, are permitted provided that: (1) source code 63c602fabSXin LI * distributions retain the above copyright notice and this paragraph 73c602fabSXin LI * in its entirety, and (2) distributions including binary code include 83c602fabSXin LI * the above copyright notice and this paragraph in its entirety in 93c602fabSXin LI * the documentation or other materials provided with the distribution. 103c602fabSXin LI * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 113c602fabSXin LI * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 123c602fabSXin LI * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 133c602fabSXin LI * FOR A PARTICULAR PURPOSE. 143c602fabSXin LI * 153c602fabSXin LI * Original code by Ola Martin Lykkja (ola.lykkja@q-free.com) 163c602fabSXin LI */ 173c602fabSXin LI 183340d773SGleb Smirnoff /* \summary: ISO CALM FAST and ETSI GeoNetworking printer */ 193340d773SGleb Smirnoff 20*ee67461eSJoseph Mingrone #include <config.h> 213c602fabSXin LI 22*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 233c602fabSXin LI 24*ee67461eSJoseph Mingrone #define ND_LONGJMP_FROM_TCHECK 253340d773SGleb Smirnoff #include "netdissect.h" 263c602fabSXin LI #include "extract.h" 273c602fabSXin LI #include "addrtoname.h" 283c602fabSXin LI 293c602fabSXin LI 303c602fabSXin LI /* 313c602fabSXin LI ETSI TS 102 636-5-1 V1.1.1 (2011-02) 323c602fabSXin LI Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking; 333c602fabSXin LI Part 5: Transport Protocols; Sub-part 1: Basic Transport Protocol 343c602fabSXin LI 353c602fabSXin LI ETSI TS 102 636-4-1 V1.1.1 (2011-06) 363c602fabSXin LI Intelligent Transport Systems (ITS); Vehicular communications; GeoNetworking; 373c602fabSXin LI Part 4: Geographical addressing and forwarding for point-to-point and point-to-multipoint communications; 383c602fabSXin LI Sub-part 1: Media-Independent Functionality 393c602fabSXin LI */ 403c602fabSXin LI 413c602fabSXin LI #define GEONET_ADDR_LEN 8 423c602fabSXin LI 433c602fabSXin LI static const struct tok msg_type_values[] = { 443c602fabSXin LI { 0, "CAM" }, 453c602fabSXin LI { 1, "DENM" }, 463c602fabSXin LI { 101, "TPEGM" }, 473c602fabSXin LI { 102, "TSPDM" }, 483c602fabSXin LI { 103, "VPM" }, 493c602fabSXin LI { 104, "SRM" }, 503c602fabSXin LI { 105, "SLAM" }, 513c602fabSXin LI { 106, "ecoCAM" }, 523c602fabSXin LI { 107, "ITM" }, 533c602fabSXin LI { 150, "SA" }, 543c602fabSXin LI { 0, NULL } 553c602fabSXin LI }; 563c602fabSXin LI 573c602fabSXin LI static void 583c602fabSXin LI print_btp_body(netdissect_options *ndo, 598bdc5a62SPatrick Kelsey const u_char *bp) 603c602fabSXin LI { 61*ee67461eSJoseph Mingrone u_int msg_type; 623c602fabSXin LI 63*ee67461eSJoseph Mingrone /* Assuming ItsPduHeader */ 64*ee67461eSJoseph Mingrone ND_PRINT("; ItsPduHeader v:%u", GET_U_1(bp)); 653c602fabSXin LI 66*ee67461eSJoseph Mingrone msg_type = GET_U_1(bp + 1); 67*ee67461eSJoseph Mingrone ND_PRINT(" t:%u-%s", msg_type, 68*ee67461eSJoseph Mingrone tok2str(msg_type_values, "unknown (%u)", msg_type)); 693c602fabSXin LI } 703c602fabSXin LI 71*ee67461eSJoseph Mingrone /* EN 302 636-5-1 V2.2.1 Section 7.2: BTP-A header */ 723c602fabSXin LI static void 733c602fabSXin LI print_btp(netdissect_options *ndo, 743c602fabSXin LI const u_char *bp) 753c602fabSXin LI { 76*ee67461eSJoseph Mingrone ND_PRINT("; BTP Dst:%u", GET_BE_U_2(bp + 0)); 77*ee67461eSJoseph Mingrone ND_PRINT(" Src:%u", GET_BE_U_2(bp + 2)); 783c602fabSXin LI } 793c602fabSXin LI 80*ee67461eSJoseph Mingrone static void 813c602fabSXin LI print_long_pos_vector(netdissect_options *ndo, 823c602fabSXin LI const u_char *bp) 833c602fabSXin LI { 84*ee67461eSJoseph Mingrone ND_PRINT("GN_ADDR:%s ", GET_LINKADDR_STRING(bp, LINKADDR_OTHER, GEONET_ADDR_LEN)); 85*ee67461eSJoseph Mingrone ND_PRINT("lat:%u ", GET_BE_U_4(bp + 12)); 86*ee67461eSJoseph Mingrone ND_PRINT("lon:%u", GET_BE_U_4(bp + 16)); 873c602fabSXin LI } 883c602fabSXin LI 893c602fabSXin LI 903c602fabSXin LI /* 913c602fabSXin LI * This is the top level routine of the printer. 'p' points 923c602fabSXin LI * to the geonet header of the packet. 933c602fabSXin LI */ 943c602fabSXin LI void 953340d773SGleb Smirnoff geonet_print(netdissect_options *ndo, const u_char *bp, u_int length, 963340d773SGleb Smirnoff const struct lladdr_info *src) 973c602fabSXin LI { 98*ee67461eSJoseph Mingrone u_int version; 99*ee67461eSJoseph Mingrone u_int next_hdr; 100*ee67461eSJoseph Mingrone u_int hdr_type; 101*ee67461eSJoseph Mingrone u_int hdr_subtype; 1028bdc5a62SPatrick Kelsey uint16_t payload_length; 103*ee67461eSJoseph Mingrone u_int hop_limit; 1043c602fabSXin LI const char *next_hdr_txt = "Unknown"; 1053c602fabSXin LI const char *hdr_type_txt = "Unknown"; 1063c602fabSXin LI int hdr_size = -1; 1073c602fabSXin LI 108*ee67461eSJoseph Mingrone ndo->ndo_protocol = "geonet"; 109*ee67461eSJoseph Mingrone ND_PRINT("GeoNet "); 1103340d773SGleb Smirnoff if (src != NULL) 111*ee67461eSJoseph Mingrone ND_PRINT("src:%s", (src->addr_string)(ndo, src->addr)); 112*ee67461eSJoseph Mingrone ND_PRINT("; "); 1138bdc5a62SPatrick Kelsey 1148bdc5a62SPatrick Kelsey /* Process Common Header */ 115*ee67461eSJoseph Mingrone if (length < 36) { 116*ee67461eSJoseph Mingrone ND_PRINT(" (common header length %u < 36)", length); 1173340d773SGleb Smirnoff goto invalid; 118*ee67461eSJoseph Mingrone } 1198bdc5a62SPatrick Kelsey 120*ee67461eSJoseph Mingrone version = GET_U_1(bp) >> 4; 121*ee67461eSJoseph Mingrone next_hdr = GET_U_1(bp) & 0x0f; 122*ee67461eSJoseph Mingrone hdr_type = GET_U_1(bp + 1) >> 4; 123*ee67461eSJoseph Mingrone hdr_subtype = GET_U_1(bp + 1) & 0x0f; 124*ee67461eSJoseph Mingrone payload_length = GET_BE_U_2(bp + 4); 125*ee67461eSJoseph Mingrone hop_limit = GET_U_1(bp + 7); 1268bdc5a62SPatrick Kelsey 1273c602fabSXin LI switch (next_hdr) { 1283c602fabSXin LI case 0: next_hdr_txt = "Any"; break; 1293c602fabSXin LI case 1: next_hdr_txt = "BTP-A"; break; 1303c602fabSXin LI case 2: next_hdr_txt = "BTP-B"; break; 1313c602fabSXin LI case 3: next_hdr_txt = "IPv6"; break; 1323c602fabSXin LI } 1333c602fabSXin LI 1343c602fabSXin LI switch (hdr_type) { 1353c602fabSXin LI case 0: hdr_type_txt = "Any"; break; 1363c602fabSXin LI case 1: hdr_type_txt = "Beacon"; break; 1373c602fabSXin LI case 2: hdr_type_txt = "GeoUnicast"; break; 1383c602fabSXin LI case 3: switch (hdr_subtype) { 1393c602fabSXin LI case 0: hdr_type_txt = "GeoAnycastCircle"; break; 1403c602fabSXin LI case 1: hdr_type_txt = "GeoAnycastRect"; break; 1413c602fabSXin LI case 2: hdr_type_txt = "GeoAnycastElipse"; break; 1423c602fabSXin LI } 1433c602fabSXin LI break; 1443c602fabSXin LI case 4: switch (hdr_subtype) { 1453c602fabSXin LI case 0: hdr_type_txt = "GeoBroadcastCircle"; break; 1463c602fabSXin LI case 1: hdr_type_txt = "GeoBroadcastRect"; break; 1473c602fabSXin LI case 2: hdr_type_txt = "GeoBroadcastElipse"; break; 1483c602fabSXin LI } 1493c602fabSXin LI break; 1503c602fabSXin LI case 5: switch (hdr_subtype) { 1513c602fabSXin LI case 0: hdr_type_txt = "TopoScopeBcast-SH"; break; 1523c602fabSXin LI case 1: hdr_type_txt = "TopoScopeBcast-MH"; break; 1533c602fabSXin LI } 1543c602fabSXin LI break; 1553c602fabSXin LI case 6: switch (hdr_subtype) { 1563c602fabSXin LI case 0: hdr_type_txt = "LocService-Request"; break; 1573c602fabSXin LI case 1: hdr_type_txt = "LocService-Reply"; break; 1583c602fabSXin LI } 1593c602fabSXin LI break; 1603c602fabSXin LI } 1613c602fabSXin LI 162*ee67461eSJoseph Mingrone ND_PRINT("v:%u ", version); 163*ee67461eSJoseph Mingrone ND_PRINT("NH:%u-%s ", next_hdr, next_hdr_txt); 164*ee67461eSJoseph Mingrone ND_PRINT("HT:%u-%u-%s ", hdr_type, hdr_subtype, hdr_type_txt); 165*ee67461eSJoseph Mingrone ND_PRINT("HopLim:%u ", hop_limit); 166*ee67461eSJoseph Mingrone ND_PRINT("Payload:%u ", payload_length); 167*ee67461eSJoseph Mingrone print_long_pos_vector(ndo, bp + 8); 1683c602fabSXin LI 1693c602fabSXin LI /* Skip Common Header */ 170*ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, 36); 1713c602fabSXin LI length -= 36; 1723c602fabSXin LI bp += 36; 1733c602fabSXin LI 1743c602fabSXin LI /* Process Extended Headers */ 1753c602fabSXin LI switch (hdr_type) { 1763c602fabSXin LI case 0: /* Any */ 1773c602fabSXin LI hdr_size = 0; 1783c602fabSXin LI break; 1793c602fabSXin LI case 1: /* Beacon */ 1803c602fabSXin LI hdr_size = 0; 1813c602fabSXin LI break; 1823c602fabSXin LI case 2: /* GeoUnicast */ 1833c602fabSXin LI break; 1843c602fabSXin LI case 3: switch (hdr_subtype) { 1853c602fabSXin LI case 0: /* GeoAnycastCircle */ 1863c602fabSXin LI break; 1873c602fabSXin LI case 1: /* GeoAnycastRect */ 1883c602fabSXin LI break; 1893c602fabSXin LI case 2: /* GeoAnycastElipse */ 1903c602fabSXin LI break; 1913c602fabSXin LI } 1923c602fabSXin LI break; 1933c602fabSXin LI case 4: switch (hdr_subtype) { 1943c602fabSXin LI case 0: /* GeoBroadcastCircle */ 1953c602fabSXin LI break; 1963c602fabSXin LI case 1: /* GeoBroadcastRect */ 1973c602fabSXin LI break; 1983c602fabSXin LI case 2: /* GeoBroadcastElipse */ 1993c602fabSXin LI break; 2003c602fabSXin LI } 2013c602fabSXin LI break; 2023c602fabSXin LI case 5: switch (hdr_subtype) { 2033c602fabSXin LI case 0: /* TopoScopeBcast-SH */ 2043c602fabSXin LI hdr_size = 0; 2053c602fabSXin LI break; 2063c602fabSXin LI case 1: /* TopoScopeBcast-MH */ 2073c602fabSXin LI hdr_size = 68 - 36; 2083c602fabSXin LI break; 2093c602fabSXin LI } 2103c602fabSXin LI break; 2113c602fabSXin LI case 6: switch (hdr_subtype) { 2123c602fabSXin LI case 0: /* LocService-Request */ 2133c602fabSXin LI break; 2143c602fabSXin LI case 1: /* LocService-Reply */ 2153c602fabSXin LI break; 2163c602fabSXin LI } 2173c602fabSXin LI break; 2183c602fabSXin LI } 2193c602fabSXin LI 2203c602fabSXin LI /* Skip Extended headers */ 2213c602fabSXin LI if (hdr_size >= 0) { 222*ee67461eSJoseph Mingrone if (length < (u_int)hdr_size) { 223*ee67461eSJoseph Mingrone ND_PRINT(" (header size %d > %u)", hdr_size, length); 2243340d773SGleb Smirnoff goto invalid; 225*ee67461eSJoseph Mingrone } 226*ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, hdr_size); 2273c602fabSXin LI length -= hdr_size; 2283c602fabSXin LI bp += hdr_size; 2293c602fabSXin LI switch (next_hdr) { 2303c602fabSXin LI case 0: /* Any */ 2313c602fabSXin LI break; 2323c602fabSXin LI case 1: 2333c602fabSXin LI case 2: /* BTP A/B */ 234*ee67461eSJoseph Mingrone if (length < 4) { 235*ee67461eSJoseph Mingrone ND_PRINT(" (BTP length %u < 4)", length); 2363340d773SGleb Smirnoff goto invalid; 237*ee67461eSJoseph Mingrone } 2383c602fabSXin LI print_btp(ndo, bp); 2393c602fabSXin LI length -= 4; 2403c602fabSXin LI bp += 4; 2418bdc5a62SPatrick Kelsey if (length >= 2) { 2428bdc5a62SPatrick Kelsey /* 2438bdc5a62SPatrick Kelsey * XXX - did print_btp_body() 2448bdc5a62SPatrick Kelsey * return if length < 2 2458bdc5a62SPatrick Kelsey * because this is optional, 2468bdc5a62SPatrick Kelsey * or was that just not 2478bdc5a62SPatrick Kelsey * reporting genuine errors? 2488bdc5a62SPatrick Kelsey */ 2498bdc5a62SPatrick Kelsey print_btp_body(ndo, bp); 2508bdc5a62SPatrick Kelsey } 2513c602fabSXin LI break; 2523c602fabSXin LI case 3: /* IPv6 */ 2533c602fabSXin LI break; 2543c602fabSXin LI } 2553c602fabSXin LI } 2563c602fabSXin LI 2573c602fabSXin LI /* Print user data part */ 2583c602fabSXin LI if (ndo->ndo_vflag) 2593c602fabSXin LI ND_DEFAULTPRINT(bp, length); 2608bdc5a62SPatrick Kelsey return; 2618bdc5a62SPatrick Kelsey 2623340d773SGleb Smirnoff invalid: 263*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 2648bdc5a62SPatrick Kelsey /* XXX - print the remaining data as hex? */ 2653c602fabSXin LI } 266