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