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