1 /* $OpenBSD: print-gre.c,v 1.6 2002/10/30 03:04:04 fgsch Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jason L. Wright 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * tcpdump filter for GRE - Generic Routing Encapsulation 36 * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE) 37 */ 38 39 #ifndef lint 40 static const char rcsid[] _U_ = 41 "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.22.2.2 2003/11/16 08:51:24 guy Exp $ (LBL)"; 42 #endif 43 44 #ifdef HAVE_CONFIG_H 45 #include "config.h" 46 #endif 47 48 #include <tcpdump-stdinc.h> 49 50 #include <stdio.h> 51 #include <string.h> 52 53 #include "interface.h" 54 #include "addrtoname.h" 55 #include "extract.h" 56 57 #include "ip.h" 58 59 #define GRE_CP 0x8000 /* checksum present */ 60 #define GRE_RP 0x4000 /* routing present */ 61 #define GRE_KP 0x2000 /* key present */ 62 #define GRE_SP 0x1000 /* sequence# present */ 63 #define GRE_sP 0x0800 /* source routing */ 64 #define GRE_RECRS 0x0700 /* recursion count */ 65 #define GRE_AP 0x0080 /* acknowledgment# present */ 66 #define GRE_VERS 0x0007 /* protocol version */ 67 68 #define GREPROTO_IP 0x0800 /* IP */ 69 #define GREPROTO_PPP 0x880b /* PPTP */ 70 #define GREPROTO_ISO 0x00fe /* OSI */ 71 72 /* source route entry types */ 73 #define GRESRE_IP 0x0800 /* IP */ 74 #define GRESRE_ASN 0xfffe /* ASN */ 75 76 void gre_print_0(const u_char *, u_int); 77 void gre_print_1(const u_char *, u_int); 78 void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int); 79 void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int); 80 void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int); 81 82 void 83 gre_print(const u_char *bp, u_int length) 84 { 85 u_int len = length, vers; 86 87 if (len < 2) { 88 printf("[|gre]"); 89 return; 90 } 91 vers = EXTRACT_16BITS(bp) & 7; 92 93 if (vers == 0) 94 gre_print_0(bp, len); 95 else if (vers == 1) 96 gre_print_1(bp, len); 97 else 98 printf("gre-unknown-version=%u", vers); 99 return; 100 101 } 102 103 void 104 gre_print_0(const u_char *bp, u_int length) 105 { 106 u_int len = length; 107 u_int16_t flags, prot; 108 109 flags = EXTRACT_16BITS(bp); 110 if (vflag) { 111 printf("[%s%s%s%s%s] ", 112 (flags & GRE_CP) ? "C" : "", 113 (flags & GRE_RP) ? "R" : "", 114 (flags & GRE_KP) ? "K" : "", 115 (flags & GRE_SP) ? "S" : "", 116 (flags & GRE_sP) ? "s" : ""); 117 } 118 119 len -= 2; 120 bp += 2; 121 122 if (len < 2) 123 goto trunc; 124 prot = EXTRACT_16BITS(bp); 125 len -= 2; 126 bp += 2; 127 128 if ((flags & GRE_CP) | (flags & GRE_RP)) { 129 if (len < 2) 130 goto trunc; 131 if (vflag) 132 printf("sum 0x%x ", EXTRACT_16BITS(bp)); 133 bp += 2; 134 len -= 2; 135 136 if (len < 2) 137 goto trunc; 138 printf("off 0x%x ", EXTRACT_16BITS(bp)); 139 bp += 2; 140 len -= 2; 141 } 142 143 if (flags & GRE_KP) { 144 if (len < 4) 145 goto trunc; 146 printf("key=0x%x ", EXTRACT_32BITS(bp)); 147 bp += 4; 148 len -= 4; 149 } 150 151 if (flags & GRE_SP) { 152 if (len < 4) 153 goto trunc; 154 printf("seq %u ", EXTRACT_32BITS(bp)); 155 bp += 4; 156 len -= 4; 157 } 158 159 if (flags & GRE_RP) { 160 for (;;) { 161 u_int16_t af; 162 u_int8_t sreoff; 163 u_int8_t srelen; 164 165 if (len < 4) 166 goto trunc; 167 af = EXTRACT_16BITS(bp); 168 sreoff = *(bp + 2); 169 srelen = *(bp + 3); 170 bp += 4; 171 len -= 4; 172 173 if (af == 0 && srelen == 0) 174 break; 175 176 gre_sre_print(af, sreoff, srelen, bp, len); 177 178 if (len < srelen) 179 goto trunc; 180 bp += srelen; 181 len -= srelen; 182 } 183 } 184 185 switch (prot) { 186 case GREPROTO_IP: 187 ip_print(bp, len); 188 break; 189 case GREPROTO_ISO: 190 isoclns_print(bp, len, len); 191 break; 192 default: 193 printf("gre-proto-0x%x", prot); 194 } 195 return; 196 197 trunc: 198 printf("[|gre]"); 199 } 200 201 void 202 gre_print_1(const u_char *bp, u_int length) 203 { 204 u_int len = length; 205 u_int16_t flags, prot; 206 207 flags = EXTRACT_16BITS(bp); 208 len -= 2; 209 bp += 2; 210 211 if (vflag) { 212 printf("[%s%s%s%s%s%s] ", 213 (flags & GRE_CP) ? "C" : "", 214 (flags & GRE_RP) ? "R" : "", 215 (flags & GRE_KP) ? "K" : "", 216 (flags & GRE_SP) ? "S" : "", 217 (flags & GRE_sP) ? "s" : "", 218 (flags & GRE_AP) ? "A" : ""); 219 } 220 221 if (len < 2) 222 goto trunc; 223 prot = EXTRACT_16BITS(bp); 224 len -= 2; 225 bp += 2; 226 227 if (flags & GRE_CP) { 228 printf("cpset!"); 229 return; 230 } 231 if (flags & GRE_RP) { 232 printf("rpset!"); 233 return; 234 } 235 if ((flags & GRE_KP) == 0) { 236 printf("kpunset!"); 237 return; 238 } 239 if (flags & GRE_sP) { 240 printf("spset!"); 241 return; 242 } 243 244 if (flags & GRE_KP) { 245 u_int32_t k; 246 247 if (len < 4) 248 goto trunc; 249 k = EXTRACT_32BITS(bp); 250 printf("call %d ", k & 0xffff); 251 len -= 4; 252 bp += 4; 253 } 254 255 if (flags & GRE_SP) { 256 if (len < 4) 257 goto trunc; 258 printf("seq %u ", EXTRACT_32BITS(bp)); 259 bp += 4; 260 len -= 4; 261 } 262 263 if (flags & GRE_AP) { 264 if (len < 4) 265 goto trunc; 266 printf("ack %u ", EXTRACT_32BITS(bp)); 267 bp += 4; 268 len -= 4; 269 } 270 271 if ((flags & GRE_SP) == 0) { 272 printf("no-payload"); 273 return; 274 } 275 276 switch (prot) { 277 case GREPROTO_PPP: 278 printf("gre-ppp-payload"); 279 break; 280 default: 281 printf("gre-proto-0x%x", prot); 282 break; 283 } 284 return; 285 286 trunc: 287 printf("[|gre]"); 288 } 289 290 void 291 gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen, 292 const u_char *bp, u_int len) 293 { 294 switch (af) { 295 case GRESRE_IP: 296 printf("(rtaf=ip"); 297 gre_sre_ip_print(sreoff, srelen, bp, len); 298 printf(") "); 299 break; 300 case GRESRE_ASN: 301 printf("(rtaf=asn"); 302 gre_sre_asn_print(sreoff, srelen, bp, len); 303 printf(") "); 304 break; 305 default: 306 printf("(rtaf=0x%x) ", af); 307 } 308 } 309 void 310 gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 311 { 312 struct in_addr a; 313 const u_char *up = bp; 314 315 if (sreoff & 3) { 316 printf(" badoffset=%u", sreoff); 317 return; 318 } 319 if (srelen & 3) { 320 printf(" badlength=%u", srelen); 321 return; 322 } 323 if (sreoff >= srelen) { 324 printf(" badoff/len=%u/%u", sreoff, srelen); 325 return; 326 } 327 328 for (;;) { 329 if (len < 4 || srelen == 0) 330 return; 331 332 memcpy(&a, bp, sizeof(a)); 333 printf(" %s%s", 334 ((bp - up) == sreoff) ? "*" : "", 335 inet_ntoa(a)); 336 337 bp += 4; 338 len -= 4; 339 srelen -= 4; 340 } 341 } 342 343 void 344 gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len) 345 { 346 const u_char *up = bp; 347 348 if (sreoff & 1) { 349 printf(" badoffset=%u", sreoff); 350 return; 351 } 352 if (srelen & 1) { 353 printf(" badlength=%u", srelen); 354 return; 355 } 356 if (sreoff >= srelen) { 357 printf(" badoff/len=%u/%u", sreoff, srelen); 358 return; 359 } 360 361 for (;;) { 362 if (len < 2 || srelen == 0) 363 return; 364 365 printf(" %s%x", 366 ((bp - up) == sreoff) ? "*" : "", 367 EXTRACT_16BITS(bp)); 368 369 bp += 2; 370 len -= 2; 371 srelen -= 2; 372 } 373 } 374