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