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