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 183c602fabSXin LI #define NETDISSECT_REWORKED 193c602fabSXin LI #ifdef HAVE_CONFIG_H 203c602fabSXin LI #include "config.h" 213c602fabSXin LI #endif 223c602fabSXin LI 233c602fabSXin LI #include <tcpdump-stdinc.h> 243c602fabSXin LI 253c602fabSXin LI #include "interface.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, 59*8bdc5a62SPatrick Kelsey const u_char *bp) 603c602fabSXin LI { 613c602fabSXin LI int version; 623c602fabSXin LI int msg_type; 633c602fabSXin LI const char *msg_type_str; 643c602fabSXin LI 653c602fabSXin LI /* Assuming ItsDpuHeader */ 663c602fabSXin LI version = bp[0]; 673c602fabSXin LI msg_type = bp[1]; 683c602fabSXin LI msg_type_str = tok2str(msg_type_values, "unknown (%u)", msg_type); 693c602fabSXin LI 703c602fabSXin LI ND_PRINT((ndo, "; ItsPduHeader v:%d t:%d-%s", version, msg_type, msg_type_str)); 713c602fabSXin LI } 723c602fabSXin LI 733c602fabSXin LI static void 743c602fabSXin LI print_btp(netdissect_options *ndo, 753c602fabSXin LI const u_char *bp) 763c602fabSXin LI { 773c602fabSXin LI uint16_t dest = EXTRACT_16BITS(bp+0); 783c602fabSXin LI uint16_t src = EXTRACT_16BITS(bp+2); 793c602fabSXin LI ND_PRINT((ndo, "; BTP Dst:%u Src:%u", dest, src)); 803c602fabSXin LI } 813c602fabSXin LI 82*8bdc5a62SPatrick Kelsey static int 833c602fabSXin LI print_long_pos_vector(netdissect_options *ndo, 843c602fabSXin LI const u_char *bp) 853c602fabSXin LI { 863c602fabSXin LI uint32_t lat, lon; 873c602fabSXin LI 883c602fabSXin LI ND_PRINT((ndo, "GN_ADDR:%s ", linkaddr_string (ndo, bp, 0, GEONET_ADDR_LEN))); 893c602fabSXin LI 90*8bdc5a62SPatrick Kelsey if (!ND_TTEST2(*(bp+12), 8)) 91*8bdc5a62SPatrick Kelsey return (-1); 923c602fabSXin LI lat = EXTRACT_32BITS(bp+12); 933c602fabSXin LI ND_PRINT((ndo, "lat:%d ", lat)); 943c602fabSXin LI lon = EXTRACT_32BITS(bp+16); 953c602fabSXin LI ND_PRINT((ndo, "lon:%d", lon)); 96*8bdc5a62SPatrick Kelsey return (0); 973c602fabSXin LI } 983c602fabSXin LI 993c602fabSXin LI 1003c602fabSXin LI /* 1013c602fabSXin LI * This is the top level routine of the printer. 'p' points 1023c602fabSXin LI * to the geonet header of the packet. 1033c602fabSXin LI */ 1043c602fabSXin LI void 1053c602fabSXin LI geonet_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int length) 1063c602fabSXin LI { 107*8bdc5a62SPatrick Kelsey int version; 108*8bdc5a62SPatrick Kelsey int next_hdr; 109*8bdc5a62SPatrick Kelsey int hdr_type; 110*8bdc5a62SPatrick Kelsey int hdr_subtype; 111*8bdc5a62SPatrick Kelsey uint16_t payload_length; 112*8bdc5a62SPatrick Kelsey int hop_limit; 1133c602fabSXin LI const char *next_hdr_txt = "Unknown"; 1143c602fabSXin LI const char *hdr_type_txt = "Unknown"; 1153c602fabSXin LI int hdr_size = -1; 1163c602fabSXin LI 117*8bdc5a62SPatrick Kelsey ND_PRINT((ndo, "GeoNet src:%s; ", etheraddr_string(ndo, eth+6))); 118*8bdc5a62SPatrick Kelsey 119*8bdc5a62SPatrick Kelsey /* Process Common Header */ 120*8bdc5a62SPatrick Kelsey if (length < 36) 121*8bdc5a62SPatrick Kelsey goto malformed; 122*8bdc5a62SPatrick Kelsey 123*8bdc5a62SPatrick Kelsey ND_TCHECK2(*bp, 7); 124*8bdc5a62SPatrick Kelsey version = bp[0] >> 4; 125*8bdc5a62SPatrick Kelsey next_hdr = bp[0] & 0x0f; 126*8bdc5a62SPatrick Kelsey hdr_type = bp[1] >> 4; 127*8bdc5a62SPatrick Kelsey hdr_subtype = bp[1] & 0x0f; 128*8bdc5a62SPatrick Kelsey payload_length = EXTRACT_16BITS(bp+4); 129*8bdc5a62SPatrick Kelsey hop_limit = bp[7]; 130*8bdc5a62SPatrick Kelsey 1313c602fabSXin LI switch (next_hdr) { 1323c602fabSXin LI case 0: next_hdr_txt = "Any"; break; 1333c602fabSXin LI case 1: next_hdr_txt = "BTP-A"; break; 1343c602fabSXin LI case 2: next_hdr_txt = "BTP-B"; break; 1353c602fabSXin LI case 3: next_hdr_txt = "IPv6"; break; 1363c602fabSXin LI } 1373c602fabSXin LI 1383c602fabSXin LI switch (hdr_type) { 1393c602fabSXin LI case 0: hdr_type_txt = "Any"; break; 1403c602fabSXin LI case 1: hdr_type_txt = "Beacon"; break; 1413c602fabSXin LI case 2: hdr_type_txt = "GeoUnicast"; break; 1423c602fabSXin LI case 3: switch (hdr_subtype) { 1433c602fabSXin LI case 0: hdr_type_txt = "GeoAnycastCircle"; break; 1443c602fabSXin LI case 1: hdr_type_txt = "GeoAnycastRect"; break; 1453c602fabSXin LI case 2: hdr_type_txt = "GeoAnycastElipse"; break; 1463c602fabSXin LI } 1473c602fabSXin LI break; 1483c602fabSXin LI case 4: switch (hdr_subtype) { 1493c602fabSXin LI case 0: hdr_type_txt = "GeoBroadcastCircle"; break; 1503c602fabSXin LI case 1: hdr_type_txt = "GeoBroadcastRect"; break; 1513c602fabSXin LI case 2: hdr_type_txt = "GeoBroadcastElipse"; break; 1523c602fabSXin LI } 1533c602fabSXin LI break; 1543c602fabSXin LI case 5: switch (hdr_subtype) { 1553c602fabSXin LI case 0: hdr_type_txt = "TopoScopeBcast-SH"; break; 1563c602fabSXin LI case 1: hdr_type_txt = "TopoScopeBcast-MH"; break; 1573c602fabSXin LI } 1583c602fabSXin LI break; 1593c602fabSXin LI case 6: switch (hdr_subtype) { 1603c602fabSXin LI case 0: hdr_type_txt = "LocService-Request"; break; 1613c602fabSXin LI case 1: hdr_type_txt = "LocService-Reply"; break; 1623c602fabSXin LI } 1633c602fabSXin LI break; 1643c602fabSXin LI } 1653c602fabSXin LI 1663c602fabSXin LI ND_PRINT((ndo, "v:%d ", version)); 1673c602fabSXin LI ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt)); 1683c602fabSXin LI ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt)); 1693c602fabSXin LI ND_PRINT((ndo, "HopLim:%d ", hop_limit)); 1703c602fabSXin LI ND_PRINT((ndo, "Payload:%d ", payload_length)); 171*8bdc5a62SPatrick Kelsey if (print_long_pos_vector(ndo, bp + 8) == -1) 172*8bdc5a62SPatrick Kelsey goto trunc; 1733c602fabSXin LI 1743c602fabSXin LI /* Skip Common Header */ 1753c602fabSXin LI length -= 36; 1763c602fabSXin LI bp += 36; 1773c602fabSXin LI 1783c602fabSXin LI /* Process Extended Headers */ 1793c602fabSXin LI switch (hdr_type) { 1803c602fabSXin LI case 0: /* Any */ 1813c602fabSXin LI hdr_size = 0; 1823c602fabSXin LI break; 1833c602fabSXin LI case 1: /* Beacon */ 1843c602fabSXin LI hdr_size = 0; 1853c602fabSXin LI break; 1863c602fabSXin LI case 2: /* GeoUnicast */ 1873c602fabSXin LI break; 1883c602fabSXin LI case 3: switch (hdr_subtype) { 1893c602fabSXin LI case 0: /* GeoAnycastCircle */ 1903c602fabSXin LI break; 1913c602fabSXin LI case 1: /* GeoAnycastRect */ 1923c602fabSXin LI break; 1933c602fabSXin LI case 2: /* GeoAnycastElipse */ 1943c602fabSXin LI break; 1953c602fabSXin LI } 1963c602fabSXin LI break; 1973c602fabSXin LI case 4: switch (hdr_subtype) { 1983c602fabSXin LI case 0: /* GeoBroadcastCircle */ 1993c602fabSXin LI break; 2003c602fabSXin LI case 1: /* GeoBroadcastRect */ 2013c602fabSXin LI break; 2023c602fabSXin LI case 2: /* GeoBroadcastElipse */ 2033c602fabSXin LI break; 2043c602fabSXin LI } 2053c602fabSXin LI break; 2063c602fabSXin LI case 5: switch (hdr_subtype) { 2073c602fabSXin LI case 0: /* TopoScopeBcast-SH */ 2083c602fabSXin LI hdr_size = 0; 2093c602fabSXin LI break; 2103c602fabSXin LI case 1: /* TopoScopeBcast-MH */ 2113c602fabSXin LI hdr_size = 68 - 36; 2123c602fabSXin LI break; 2133c602fabSXin LI } 2143c602fabSXin LI break; 2153c602fabSXin LI case 6: switch (hdr_subtype) { 2163c602fabSXin LI case 0: /* LocService-Request */ 2173c602fabSXin LI break; 2183c602fabSXin LI case 1: /* LocService-Reply */ 2193c602fabSXin LI break; 2203c602fabSXin LI } 2213c602fabSXin LI break; 2223c602fabSXin LI } 2233c602fabSXin LI 2243c602fabSXin LI /* Skip Extended headers */ 2253c602fabSXin LI if (hdr_size >= 0) { 226*8bdc5a62SPatrick Kelsey if (length < (u_int)hdr_size) 227*8bdc5a62SPatrick Kelsey goto malformed; 228*8bdc5a62SPatrick Kelsey ND_TCHECK2(*bp, hdr_size); 2293c602fabSXin LI length -= hdr_size; 2303c602fabSXin LI bp += hdr_size; 2313c602fabSXin LI switch (next_hdr) { 2323c602fabSXin LI case 0: /* Any */ 2333c602fabSXin LI break; 2343c602fabSXin LI case 1: 2353c602fabSXin LI case 2: /* BTP A/B */ 236*8bdc5a62SPatrick Kelsey if (length < 4) 237*8bdc5a62SPatrick Kelsey goto malformed; 238*8bdc5a62SPatrick Kelsey ND_TCHECK2(*bp, 4); 2393c602fabSXin LI print_btp(ndo, bp); 2403c602fabSXin LI length -= 4; 2413c602fabSXin LI bp += 4; 242*8bdc5a62SPatrick Kelsey if (length >= 2) { 243*8bdc5a62SPatrick Kelsey /* 244*8bdc5a62SPatrick Kelsey * XXX - did print_btp_body() 245*8bdc5a62SPatrick Kelsey * return if length < 2 246*8bdc5a62SPatrick Kelsey * because this is optional, 247*8bdc5a62SPatrick Kelsey * or was that just not 248*8bdc5a62SPatrick Kelsey * reporting genuine errors? 249*8bdc5a62SPatrick Kelsey */ 250*8bdc5a62SPatrick Kelsey ND_TCHECK2(*bp, 2); 251*8bdc5a62SPatrick Kelsey print_btp_body(ndo, bp); 252*8bdc5a62SPatrick Kelsey } 2533c602fabSXin LI break; 2543c602fabSXin LI case 3: /* IPv6 */ 2553c602fabSXin LI break; 2563c602fabSXin LI } 2573c602fabSXin LI } 2583c602fabSXin LI 2593c602fabSXin LI /* Print user data part */ 2603c602fabSXin LI if (ndo->ndo_vflag) 2613c602fabSXin LI ND_DEFAULTPRINT(bp, length); 262*8bdc5a62SPatrick Kelsey return; 263*8bdc5a62SPatrick Kelsey 264*8bdc5a62SPatrick Kelsey malformed: 265*8bdc5a62SPatrick Kelsey ND_PRINT((ndo, " Malformed (small) ")); 266*8bdc5a62SPatrick Kelsey /* XXX - print the remaining data as hex? */ 267*8bdc5a62SPatrick Kelsey return; 268*8bdc5a62SPatrick Kelsey 269*8bdc5a62SPatrick Kelsey trunc: 270*8bdc5a62SPatrick Kelsey ND_PRINT((ndo, "[|geonet]")); 2713c602fabSXin LI } 2723c602fabSXin LI 2733c602fabSXin LI 2743c602fabSXin LI /* 2753c602fabSXin LI * Local Variables: 2763c602fabSXin LI * c-style: whitesmith 2773c602fabSXin LI * c-basic-offset: 8 2783c602fabSXin LI * End: 2793c602fabSXin LI */ 280