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 18*3340d773SGleb Smirnoff /* \summary: ISO CALM FAST and ETSI GeoNetworking printer */ 19*3340d773SGleb Smirnoff 203c602fabSXin LI #ifdef HAVE_CONFIG_H 213c602fabSXin LI #include "config.h" 223c602fabSXin LI #endif 233c602fabSXin LI 24*3340d773SGleb Smirnoff #include <netdissect-stdinc.h> 253c602fabSXin LI 26*3340d773SGleb Smirnoff #include "netdissect.h" 273c602fabSXin LI #include "extract.h" 283c602fabSXin LI #include "addrtoname.h" 293c602fabSXin LI 303c602fabSXin LI 313c602fabSXin LI /* 323c602fabSXin LI ETSI TS 102 636-5-1 V1.1.1 (2011-02) 333c602fabSXin LI Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking; 343c602fabSXin LI Part 5: Transport Protocols; Sub-part 1: Basic Transport Protocol 353c602fabSXin LI 363c602fabSXin LI ETSI TS 102 636-4-1 V1.1.1 (2011-06) 373c602fabSXin LI Intelligent Transport Systems (ITS); Vehicular communications; GeoNetworking; 383c602fabSXin LI Part 4: Geographical addressing and forwarding for point-to-point and point-to-multipoint communications; 393c602fabSXin LI Sub-part 1: Media-Independent Functionality 403c602fabSXin LI */ 413c602fabSXin LI 423c602fabSXin LI #define GEONET_ADDR_LEN 8 433c602fabSXin LI 443c602fabSXin LI static const struct tok msg_type_values[] = { 453c602fabSXin LI { 0, "CAM" }, 463c602fabSXin LI { 1, "DENM" }, 473c602fabSXin LI { 101, "TPEGM" }, 483c602fabSXin LI { 102, "TSPDM" }, 493c602fabSXin LI { 103, "VPM" }, 503c602fabSXin LI { 104, "SRM" }, 513c602fabSXin LI { 105, "SLAM" }, 523c602fabSXin LI { 106, "ecoCAM" }, 533c602fabSXin LI { 107, "ITM" }, 543c602fabSXin LI { 150, "SA" }, 553c602fabSXin LI { 0, NULL } 563c602fabSXin LI }; 573c602fabSXin LI 583c602fabSXin LI static void 593c602fabSXin LI print_btp_body(netdissect_options *ndo, 608bdc5a62SPatrick Kelsey const u_char *bp) 613c602fabSXin LI { 623c602fabSXin LI int version; 633c602fabSXin LI int msg_type; 643c602fabSXin LI const char *msg_type_str; 653c602fabSXin LI 663c602fabSXin LI /* Assuming ItsDpuHeader */ 673c602fabSXin LI version = bp[0]; 683c602fabSXin LI msg_type = bp[1]; 693c602fabSXin LI msg_type_str = tok2str(msg_type_values, "unknown (%u)", msg_type); 703c602fabSXin LI 713c602fabSXin LI ND_PRINT((ndo, "; ItsPduHeader v:%d t:%d-%s", version, msg_type, msg_type_str)); 723c602fabSXin LI } 733c602fabSXin LI 743c602fabSXin LI static void 753c602fabSXin LI print_btp(netdissect_options *ndo, 763c602fabSXin LI const u_char *bp) 773c602fabSXin LI { 783c602fabSXin LI uint16_t dest = EXTRACT_16BITS(bp+0); 793c602fabSXin LI uint16_t src = EXTRACT_16BITS(bp+2); 803c602fabSXin LI ND_PRINT((ndo, "; BTP Dst:%u Src:%u", dest, src)); 813c602fabSXin LI } 823c602fabSXin LI 838bdc5a62SPatrick Kelsey static int 843c602fabSXin LI print_long_pos_vector(netdissect_options *ndo, 853c602fabSXin LI const u_char *bp) 863c602fabSXin LI { 873c602fabSXin LI uint32_t lat, lon; 883c602fabSXin LI 89*3340d773SGleb Smirnoff if (!ND_TTEST2(*bp, GEONET_ADDR_LEN)) 90*3340d773SGleb Smirnoff return (-1); 913c602fabSXin LI ND_PRINT((ndo, "GN_ADDR:%s ", linkaddr_string (ndo, bp, 0, GEONET_ADDR_LEN))); 923c602fabSXin LI 938bdc5a62SPatrick Kelsey if (!ND_TTEST2(*(bp+12), 8)) 948bdc5a62SPatrick Kelsey return (-1); 953c602fabSXin LI lat = EXTRACT_32BITS(bp+12); 963c602fabSXin LI ND_PRINT((ndo, "lat:%d ", lat)); 973c602fabSXin LI lon = EXTRACT_32BITS(bp+16); 983c602fabSXin LI ND_PRINT((ndo, "lon:%d", lon)); 998bdc5a62SPatrick Kelsey return (0); 1003c602fabSXin LI } 1013c602fabSXin LI 1023c602fabSXin LI 1033c602fabSXin LI /* 1043c602fabSXin LI * This is the top level routine of the printer. 'p' points 1053c602fabSXin LI * to the geonet header of the packet. 1063c602fabSXin LI */ 1073c602fabSXin LI void 108*3340d773SGleb Smirnoff geonet_print(netdissect_options *ndo, const u_char *bp, u_int length, 109*3340d773SGleb Smirnoff const struct lladdr_info *src) 1103c602fabSXin LI { 1118bdc5a62SPatrick Kelsey int version; 1128bdc5a62SPatrick Kelsey int next_hdr; 1138bdc5a62SPatrick Kelsey int hdr_type; 1148bdc5a62SPatrick Kelsey int hdr_subtype; 1158bdc5a62SPatrick Kelsey uint16_t payload_length; 1168bdc5a62SPatrick Kelsey int hop_limit; 1173c602fabSXin LI const char *next_hdr_txt = "Unknown"; 1183c602fabSXin LI const char *hdr_type_txt = "Unknown"; 1193c602fabSXin LI int hdr_size = -1; 1203c602fabSXin LI 121*3340d773SGleb Smirnoff ND_PRINT((ndo, "GeoNet ")); 122*3340d773SGleb Smirnoff if (src != NULL) 123*3340d773SGleb Smirnoff ND_PRINT((ndo, "src:%s", (src->addr_string)(ndo, src->addr))); 124*3340d773SGleb Smirnoff ND_PRINT((ndo, "; ")); 1258bdc5a62SPatrick Kelsey 1268bdc5a62SPatrick Kelsey /* Process Common Header */ 1278bdc5a62SPatrick Kelsey if (length < 36) 128*3340d773SGleb Smirnoff goto invalid; 1298bdc5a62SPatrick Kelsey 130*3340d773SGleb Smirnoff ND_TCHECK2(*bp, 8); 1318bdc5a62SPatrick Kelsey version = bp[0] >> 4; 1328bdc5a62SPatrick Kelsey next_hdr = bp[0] & 0x0f; 1338bdc5a62SPatrick Kelsey hdr_type = bp[1] >> 4; 1348bdc5a62SPatrick Kelsey hdr_subtype = bp[1] & 0x0f; 1358bdc5a62SPatrick Kelsey payload_length = EXTRACT_16BITS(bp+4); 1368bdc5a62SPatrick Kelsey hop_limit = bp[7]; 1378bdc5a62SPatrick Kelsey 1383c602fabSXin LI switch (next_hdr) { 1393c602fabSXin LI case 0: next_hdr_txt = "Any"; break; 1403c602fabSXin LI case 1: next_hdr_txt = "BTP-A"; break; 1413c602fabSXin LI case 2: next_hdr_txt = "BTP-B"; break; 1423c602fabSXin LI case 3: next_hdr_txt = "IPv6"; break; 1433c602fabSXin LI } 1443c602fabSXin LI 1453c602fabSXin LI switch (hdr_type) { 1463c602fabSXin LI case 0: hdr_type_txt = "Any"; break; 1473c602fabSXin LI case 1: hdr_type_txt = "Beacon"; break; 1483c602fabSXin LI case 2: hdr_type_txt = "GeoUnicast"; break; 1493c602fabSXin LI case 3: switch (hdr_subtype) { 1503c602fabSXin LI case 0: hdr_type_txt = "GeoAnycastCircle"; break; 1513c602fabSXin LI case 1: hdr_type_txt = "GeoAnycastRect"; break; 1523c602fabSXin LI case 2: hdr_type_txt = "GeoAnycastElipse"; break; 1533c602fabSXin LI } 1543c602fabSXin LI break; 1553c602fabSXin LI case 4: switch (hdr_subtype) { 1563c602fabSXin LI case 0: hdr_type_txt = "GeoBroadcastCircle"; break; 1573c602fabSXin LI case 1: hdr_type_txt = "GeoBroadcastRect"; break; 1583c602fabSXin LI case 2: hdr_type_txt = "GeoBroadcastElipse"; break; 1593c602fabSXin LI } 1603c602fabSXin LI break; 1613c602fabSXin LI case 5: switch (hdr_subtype) { 1623c602fabSXin LI case 0: hdr_type_txt = "TopoScopeBcast-SH"; break; 1633c602fabSXin LI case 1: hdr_type_txt = "TopoScopeBcast-MH"; break; 1643c602fabSXin LI } 1653c602fabSXin LI break; 1663c602fabSXin LI case 6: switch (hdr_subtype) { 1673c602fabSXin LI case 0: hdr_type_txt = "LocService-Request"; break; 1683c602fabSXin LI case 1: hdr_type_txt = "LocService-Reply"; break; 1693c602fabSXin LI } 1703c602fabSXin LI break; 1713c602fabSXin LI } 1723c602fabSXin LI 1733c602fabSXin LI ND_PRINT((ndo, "v:%d ", version)); 1743c602fabSXin LI ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt)); 1753c602fabSXin LI ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt)); 1763c602fabSXin LI ND_PRINT((ndo, "HopLim:%d ", hop_limit)); 1773c602fabSXin LI ND_PRINT((ndo, "Payload:%d ", payload_length)); 1788bdc5a62SPatrick Kelsey if (print_long_pos_vector(ndo, bp + 8) == -1) 1798bdc5a62SPatrick Kelsey goto trunc; 1803c602fabSXin LI 1813c602fabSXin LI /* Skip Common Header */ 1823c602fabSXin LI length -= 36; 1833c602fabSXin LI bp += 36; 1843c602fabSXin LI 1853c602fabSXin LI /* Process Extended Headers */ 1863c602fabSXin LI switch (hdr_type) { 1873c602fabSXin LI case 0: /* Any */ 1883c602fabSXin LI hdr_size = 0; 1893c602fabSXin LI break; 1903c602fabSXin LI case 1: /* Beacon */ 1913c602fabSXin LI hdr_size = 0; 1923c602fabSXin LI break; 1933c602fabSXin LI case 2: /* GeoUnicast */ 1943c602fabSXin LI break; 1953c602fabSXin LI case 3: switch (hdr_subtype) { 1963c602fabSXin LI case 0: /* GeoAnycastCircle */ 1973c602fabSXin LI break; 1983c602fabSXin LI case 1: /* GeoAnycastRect */ 1993c602fabSXin LI break; 2003c602fabSXin LI case 2: /* GeoAnycastElipse */ 2013c602fabSXin LI break; 2023c602fabSXin LI } 2033c602fabSXin LI break; 2043c602fabSXin LI case 4: switch (hdr_subtype) { 2053c602fabSXin LI case 0: /* GeoBroadcastCircle */ 2063c602fabSXin LI break; 2073c602fabSXin LI case 1: /* GeoBroadcastRect */ 2083c602fabSXin LI break; 2093c602fabSXin LI case 2: /* GeoBroadcastElipse */ 2103c602fabSXin LI break; 2113c602fabSXin LI } 2123c602fabSXin LI break; 2133c602fabSXin LI case 5: switch (hdr_subtype) { 2143c602fabSXin LI case 0: /* TopoScopeBcast-SH */ 2153c602fabSXin LI hdr_size = 0; 2163c602fabSXin LI break; 2173c602fabSXin LI case 1: /* TopoScopeBcast-MH */ 2183c602fabSXin LI hdr_size = 68 - 36; 2193c602fabSXin LI break; 2203c602fabSXin LI } 2213c602fabSXin LI break; 2223c602fabSXin LI case 6: switch (hdr_subtype) { 2233c602fabSXin LI case 0: /* LocService-Request */ 2243c602fabSXin LI break; 2253c602fabSXin LI case 1: /* LocService-Reply */ 2263c602fabSXin LI break; 2273c602fabSXin LI } 2283c602fabSXin LI break; 2293c602fabSXin LI } 2303c602fabSXin LI 2313c602fabSXin LI /* Skip Extended headers */ 2323c602fabSXin LI if (hdr_size >= 0) { 2338bdc5a62SPatrick Kelsey if (length < (u_int)hdr_size) 234*3340d773SGleb Smirnoff goto invalid; 2358bdc5a62SPatrick Kelsey ND_TCHECK2(*bp, hdr_size); 2363c602fabSXin LI length -= hdr_size; 2373c602fabSXin LI bp += hdr_size; 2383c602fabSXin LI switch (next_hdr) { 2393c602fabSXin LI case 0: /* Any */ 2403c602fabSXin LI break; 2413c602fabSXin LI case 1: 2423c602fabSXin LI case 2: /* BTP A/B */ 2438bdc5a62SPatrick Kelsey if (length < 4) 244*3340d773SGleb Smirnoff goto invalid; 2458bdc5a62SPatrick Kelsey ND_TCHECK2(*bp, 4); 2463c602fabSXin LI print_btp(ndo, bp); 2473c602fabSXin LI length -= 4; 2483c602fabSXin LI bp += 4; 2498bdc5a62SPatrick Kelsey if (length >= 2) { 2508bdc5a62SPatrick Kelsey /* 2518bdc5a62SPatrick Kelsey * XXX - did print_btp_body() 2528bdc5a62SPatrick Kelsey * return if length < 2 2538bdc5a62SPatrick Kelsey * because this is optional, 2548bdc5a62SPatrick Kelsey * or was that just not 2558bdc5a62SPatrick Kelsey * reporting genuine errors? 2568bdc5a62SPatrick Kelsey */ 2578bdc5a62SPatrick Kelsey ND_TCHECK2(*bp, 2); 2588bdc5a62SPatrick Kelsey print_btp_body(ndo, bp); 2598bdc5a62SPatrick Kelsey } 2603c602fabSXin LI break; 2613c602fabSXin LI case 3: /* IPv6 */ 2623c602fabSXin LI break; 2633c602fabSXin LI } 2643c602fabSXin LI } 2653c602fabSXin LI 2663c602fabSXin LI /* Print user data part */ 2673c602fabSXin LI if (ndo->ndo_vflag) 2683c602fabSXin LI ND_DEFAULTPRINT(bp, length); 2698bdc5a62SPatrick Kelsey return; 2708bdc5a62SPatrick Kelsey 271*3340d773SGleb Smirnoff invalid: 2728bdc5a62SPatrick Kelsey ND_PRINT((ndo, " Malformed (small) ")); 2738bdc5a62SPatrick Kelsey /* XXX - print the remaining data as hex? */ 2748bdc5a62SPatrick Kelsey return; 2758bdc5a62SPatrick Kelsey 2768bdc5a62SPatrick Kelsey trunc: 2778bdc5a62SPatrick Kelsey ND_PRINT((ndo, "[|geonet]")); 2783c602fabSXin LI } 2793c602fabSXin LI 2803c602fabSXin LI 2813c602fabSXin LI /* 2823c602fabSXin LI * Local Variables: 2833c602fabSXin LI * c-style: whitesmith 2843c602fabSXin LI * c-basic-offset: 8 2853c602fabSXin LI * End: 2863c602fabSXin LI */ 287