print-ip.c revision 17691
1/* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22#ifndef lint 23static char rcsid[] = 24 "@(#) $Header: print-ip.c,v 1.56 96/07/23 14:17:24 leres Exp $ (LBL)"; 25#endif 26 27#include <sys/param.h> 28#include <sys/time.h> 29#include <sys/socket.h> 30 31#include <netinet/in.h> 32#include <netinet/in_systm.h> 33#include <netinet/ip.h> 34#include <netinet/ip_var.h> 35#include <netinet/udp.h> 36#include <netinet/udp_var.h> 37#include <netinet/tcp.h> 38#include <netinet/tcpip.h> 39 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43#include <unistd.h> 44 45#include "addrtoname.h" 46#include "interface.h" 47#include "extract.h" /* must come after interface.h */ 48 49/* Compatibility */ 50#ifndef IPPROTO_ND 51#define IPPROTO_ND 77 52#endif 53 54#ifndef IN_CLASSD 55#define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000) 56#endif 57 58/* (following from ipmulti/mrouted/prune.h) */ 59 60/* 61 * The packet format for a traceroute request. 62 */ 63struct tr_query { 64 u_int tr_src; /* traceroute source */ 65 u_int tr_dst; /* traceroute destination */ 66 u_int tr_raddr; /* traceroute response address */ 67#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) 68 struct { 69 u_int qid : 24; /* traceroute query id */ 70 u_int ttl : 8; /* traceroute response ttl */ 71 } q; 72#else 73 struct { 74 u_int ttl : 8; /* traceroute response ttl */ 75 u_int qid : 24; /* traceroute query id */ 76 } q; 77#endif /* BYTE_ORDER */ 78}; 79 80#define tr_rttl q.ttl 81#define tr_qid q.qid 82 83/* 84 * Traceroute response format. A traceroute response has a tr_query at the 85 * beginning, followed by one tr_resp for each hop taken. 86 */ 87struct tr_resp { 88 u_int tr_qarr; /* query arrival time */ 89 u_int tr_inaddr; /* incoming interface address */ 90 u_int tr_outaddr; /* outgoing interface address */ 91 u_int tr_rmtaddr; /* parent address in source tree */ 92 u_int tr_vifin; /* input packet count on interface */ 93 u_int tr_vifout; /* output packet count on interface */ 94 u_int tr_pktcnt; /* total incoming packets for src-grp */ 95 u_char tr_rproto; /* routing proto deployed on router */ 96 u_char tr_fttl; /* ttl required to forward on outvif */ 97 u_char tr_smask; /* subnet mask for src addr */ 98 u_char tr_rflags; /* forwarding error codes */ 99}; 100 101/* defs within mtrace */ 102#define TR_QUERY 1 103#define TR_RESP 2 104 105/* fields for tr_rflags (forwarding error codes) */ 106#define TR_NO_ERR 0 107#define TR_WRONG_IF 1 108#define TR_PRUNED 2 109#define TR_OPRUNED 3 110#define TR_SCOPED 4 111#define TR_NO_RTE 5 112#define TR_NO_FWD 7 113#define TR_NO_SPACE 0x81 114#define TR_OLD_ROUTER 0x82 115 116/* fields for tr_rproto (routing protocol) */ 117#define TR_PROTO_DVMRP 1 118#define TR_PROTO_MOSPF 2 119#define TR_PROTO_PIM 3 120#define TR_PROTO_CBT 4 121 122static void print_mtrace(register const u_char *bp, register u_int len) 123{ 124 register struct tr_query* tr = (struct tr_query*)(bp + 8); 125 126 printf("mtrace %d: %s to %s reply-to %s", tr->tr_qid, 127 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), 128 ipaddr_string(&tr->tr_raddr)); 129 if (IN_CLASSD(ntohl(tr->tr_raddr))) 130 printf(" with-ttl %d", tr->tr_rttl); 131} 132 133static void print_mresp(register const u_char *bp, register u_int len) 134{ 135 register struct tr_query* tr = (struct tr_query*)(bp + 8); 136 137 printf("mresp %d: %s to %s reply-to %s", tr->tr_qid, 138 ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), 139 ipaddr_string(&tr->tr_raddr)); 140 if (IN_CLASSD(ntohl(tr->tr_raddr))) 141 printf(" with-ttl %d", tr->tr_rttl); 142} 143 144static void 145igmp_print(register const u_char *bp, register u_int len, 146 register const u_char *bp2) 147{ 148 register const struct ip *ip; 149 150 ip = (const struct ip *)bp2; 151 (void)printf("%s > %s: ", 152 ipaddr_string(&ip->ip_src), 153 ipaddr_string(&ip->ip_dst)); 154 155 TCHECK2(bp[0], 8); 156 switch (bp[0]) { 157 case 0x11: 158 (void)printf("igmp %s query", bp[1] ? "v2" : "v1"); 159 if (bp[1] && bp[1] != 100) 160 (void)printf(" [intvl %d]", bp[1]); 161 if (*(int *)&bp[4]) 162 (void)printf(" [gaddr %s]", ipaddr_string(&bp[4])); 163 if (len != 8) 164 (void)printf(" [len %d]", len); 165 break; 166 case 0x12: 167 case 0x16: 168 (void)printf("igmp %s report %s", 169 bp[0] & 0x0f == 6 ? "v2" : "v1", 170 ipaddr_string(&bp[4])); 171 if (len != 8) 172 (void)printf(" [len %d]", len); 173 if (bp[1]) 174 (void)printf(" [b1=0x%x]", bp[1]); 175 break; 176 case 0x17: 177 (void)printf("igmp leave %s", ipaddr_string(&bp[4])); 178 switch(bp[1]) { 179 case 1: 180 (void)printf(" probe"); 181 if (len < 8) 182 (void)printf(" [len %d]", len); 183 if (vflag) { 184 if (len > 8) 185 (void)printf(" genid 0x%08x", 186 ntohl(*(u_int32_t *)&bp[8])); 187 (void)printf(" [nf 0x%02x]", bp[5]); 188 } 189 if (len > 12) { 190 int i; 191 for (i = 12; i + 3 < len; i += 4) 192 (void)printf("\n\t%s", 193 ipaddr_string(&bp[i])); 194 } 195 break; 196 case 2: 197 (void)printf(" report"); 198 if (vflag) 199 (void)printf(" [nf 0x%02x]", bp[5]); 200 if (len < 8) 201 (void)printf(" [len %d]", len); 202 break; 203 case 3: 204 case 5: 205 (void)printf(" %sneighbor query", 206 bp[1] == 5 ? "new " : ""); 207 if (len < 8) 208 (void)printf(" [len %d]", len); 209 break; 210 case 4: 211 case 6: 212 (void)printf(" %sneighbor list", 213 bp[1] == 6 ? "new " : ""); 214 if (len < 8) 215 (void)printf(" [len %d]", len); 216 break; 217 case 7: 218 (void)printf(" prune %s from ", ipaddr_string(&bp[12])); 219 (void)printf(" %s timer %d", ipaddr_string(&bp[8]), 220 ntohl(*(u_int32_t *)&bp[16])); 221 if (len != 20) 222 (void)printf(" [len %d]", len); 223 break; 224 case 8: 225 (void)printf(" graft %s from ", ipaddr_string(&bp[12])); 226 (void)printf(" %s", ipaddr_string(&bp[8])); 227 if (len != 16) 228 (void)printf(" [len %d]", len); 229 break; 230 case 9: 231 (void)printf(" graft ack %s from ", 232 ipaddr_string(&bp[12])); 233 (void)printf(" %s", ipaddr_string(&bp[8])); 234 if (len != 16) 235 (void)printf(" [len %d]", len); 236 break; 237 default: 238 (void)printf("-%d", bp[1]); 239 if (len != 8) 240 (void)printf(" [len %d]", len); 241 break; 242 } 243 244 if (bp[7] != 3 || (bp[7] == 3 && (bp[6] > 5 || bp[6] < 4))) 245 (void)printf(" [v%d.%d]", bp[7], bp[6]); 246 247 break; 248 case 0x13: 249 (void)printf("igmp dvmrp"); 250 if (len < 8) 251 (void)printf(" [len %d]", len); 252 else 253 dvmrp_print(bp, len); 254 break; 255 case 0x14: 256 (void)printf("igmp pim"); 257 pim_print(bp, len); 258 break; 259 case 0x1e: 260 print_mresp(bp, len); 261 break; 262 case 0x1f: 263 print_mtrace(bp, len); 264 break; 265 default: 266 (void)printf("igmp-%d", bp[0] & 0xf); 267 if (bp[1]) 268 (void)printf(" [b1=0x%02x]", bp[1]); 269 break; 270 } 271 272 TCHECK2(bp[0], len); 273 if (vflag) { 274 /* Check the IGMP checksum */ 275 u_int32_t sum = 0; 276 int count; 277 const u_short *sp = (u_short*)bp; 278 279 for (count = len / 2; --count >= 0; ) 280 sum += *sp++; 281 if (len & 1) 282 sum += ntohs(*(unsigned char*) sp << 8); 283 while (sum >> 16) 284 sum = (sum & 0xffff) + (sum >> 16); 285 sum = 0xffff & ~sum; 286 if (sum != 0) 287 printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2])); 288 } 289 return; 290trunc: 291 fputs("[|igmp]", stdout); 292} 293 294/* 295 * print the recorded route in an IP RR, LSRR or SSRR option. 296 */ 297static void 298ip_printroute(const char *type, register const u_char *cp, u_int length) 299{ 300 register u_int ptr = cp[2] - 1; 301 register u_int len; 302 303 printf(" %s{", type); 304 if ((length + 1) & 3) 305 printf(" [bad length %d]", length); 306 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) 307 printf(" [bad ptr %d]", cp[2]); 308 309 type = ""; 310 for (len = 3; len < length; len += 4) { 311 if (ptr == len) 312 type = "#"; 313 printf("%s%s", type, ipaddr_string(&cp[len])); 314 type = " "; 315 } 316 printf("%s}", ptr == len? "#" : ""); 317} 318 319/* 320 * print IP options. 321 */ 322static void 323ip_optprint(register const u_char *cp, u_int length) 324{ 325 register u_int len; 326 327 for (; length > 0; cp += len, length -= len) { 328 int tt = *cp; 329 330 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1]; 331 if (len <= 0) { 332 printf("[|ip op len %d]", len); 333 return; 334 } 335 if (&cp[1] >= snapend || cp + len > snapend) { 336 printf("[|ip]"); 337 return; 338 } 339 switch (tt) { 340 341 case IPOPT_EOL: 342 printf(" EOL"); 343 if (length > 1) 344 printf("-%d", length - 1); 345 return; 346 347 case IPOPT_NOP: 348 printf(" NOP"); 349 break; 350 351 case IPOPT_TS: 352 printf(" TS{%d}", len); 353 break; 354 355 case IPOPT_SECURITY: 356 printf(" SECURITY{%d}", len); 357 break; 358 359 case IPOPT_RR: 360 printf(" RR{%d}=", len); 361 ip_printroute("RR", cp, len); 362 break; 363 364 case IPOPT_SSRR: 365 ip_printroute("SSRR", cp, len); 366 break; 367 368 case IPOPT_LSRR: 369 ip_printroute("LSRR", cp, len); 370 break; 371 372 case IPOPT_RA: 373 printf(" RA{%d}", len); 374 if (cp[2] != 0 || cp[3] != 0) 375 printf(" [b23=0x04%x]", cp[2] << 8 | cp[3]); 376 break; 377 378 default: 379 printf(" IPOPT-%d{%d}", cp[0], len); 380 break; 381 } 382 } 383} 384 385/* 386 * compute an IP header checksum. 387 * don't modifiy the packet. 388 */ 389static int 390in_cksum(const struct ip *ip) 391{ 392 register const u_short *sp = (u_short *)ip; 393 register u_int32_t sum = 0; 394 register int count; 395 396 /* 397 * No need for endian conversions. 398 */ 399 for (count = ip->ip_hl * 2; --count >= 0; ) 400 sum += *sp++; 401 while (sum > 0xffff) 402 sum = (sum & 0xffff) + (sum >> 16); 403 sum = ~sum & 0xffff; 404 405 return (sum); 406} 407 408/* 409 * print an IP datagram. 410 */ 411void 412ip_print(register const u_char *bp, register u_int length) 413{ 414 register const struct ip *ip; 415 register u_int hlen, len, off; 416 register const u_char *cp; 417 418 ip = (const struct ip *)bp; 419#ifdef LBL_ALIGN 420 /* 421 * If the IP header is not aligned, copy into abuf. 422 * This will never happen with BPF. It does happen raw packet 423 * dumps from -r. 424 */ 425 if ((long)ip & 3) { 426 static u_char *abuf = NULL; 427 static int didwarn = 0; 428 429 if (abuf == NULL) { 430 abuf = (u_char *)malloc(snaplen); 431 if (abuf == NULL) 432 error("ip_print: malloc"); 433 } 434 memcpy((char *)abuf, (char *)ip, min(length, snaplen)); 435 snapend += abuf - (u_char *)ip; 436 packetp = abuf; 437 ip = (struct ip *)abuf; 438 /* We really want libpcap to give us aligned packets */ 439 if (!didwarn) { 440 warning("compensating for unaligned libpcap packets"); 441 ++didwarn; 442 } 443 } 444#endif 445 if ((u_char *)(ip + 1) > snapend) { 446 printf("[|ip]"); 447 return; 448 } 449 if (length < sizeof (struct ip)) { 450 (void)printf("truncated-ip %d", length); 451 return; 452 } 453 hlen = ip->ip_hl * 4; 454 455 len = ntohs(ip->ip_len); 456 if (length < len) 457 (void)printf("truncated-ip - %d bytes missing!", 458 len - length); 459 len -= hlen; 460 461 /* 462 * If this is fragment zero, hand it to the next higher 463 * level protocol. 464 */ 465 off = ntohs(ip->ip_off); 466 if ((off & 0x1fff) == 0) { 467 cp = (const u_char *)ip + hlen; 468 switch (ip->ip_p) { 469 470 case IPPROTO_TCP: 471 tcp_print(cp, len, (const u_char *)ip); 472 break; 473 474 case IPPROTO_UDP: 475 udp_print(cp, len, (const u_char *)ip); 476 break; 477 478 case IPPROTO_ICMP: 479 icmp_print(cp, (const u_char *)ip); 480 break; 481 482#ifndef IPPROTO_IGRP 483#define IPPROTO_IGRP 9 484#endif 485 case IPPROTO_IGRP: 486 igrp_print(cp, len, (const u_char *)ip); 487 break; 488 489 case IPPROTO_ND: 490 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 491 ipaddr_string(&ip->ip_dst)); 492 (void)printf(" nd %d", len); 493 break; 494 495 case IPPROTO_EGP: 496 egp_print(cp, len, (const u_char *)ip); 497 break; 498 499#ifndef IPPROTO_OSPF 500#define IPPROTO_OSPF 89 501#endif 502 case IPPROTO_OSPF: 503 ospf_print(cp, len, (const u_char *)ip); 504 break; 505 506#ifndef IPPROTO_IGMP 507#define IPPROTO_IGMP 2 508#endif 509 case IPPROTO_IGMP: 510 igmp_print(cp, len, (const u_char *)ip); 511 break; 512 513#ifndef IPPROTO_ENCAP 514#define IPPROTO_ENCAP 4 515#endif 516 case IPPROTO_ENCAP: 517 /* ip-in-ip encapsulation */ 518 if (vflag) 519 (void)printf("%s > %s: ", 520 ipaddr_string(&ip->ip_src), 521 ipaddr_string(&ip->ip_dst)); 522 ip_print(cp, len); 523 if (! vflag) { 524 printf(" (encap)"); 525 return; 526 } 527 break; 528 529 default: 530 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 531 ipaddr_string(&ip->ip_dst)); 532 (void)printf(" ip-proto-%d %d", ip->ip_p, len); 533 break; 534 } 535 } 536 /* 537 * for fragmented datagrams, print id:size@offset. On all 538 * but the last stick a "+". For unfragmented datagrams, note 539 * the don't fragment flag. 540 */ 541 if (off & 0x3fff) { 542 /* 543 * if this isn't the first frag, we're missing the 544 * next level protocol header. print the ip addr. 545 */ 546 if (off & 0x1fff) 547 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 548 ipaddr_string(&ip->ip_dst)); 549 (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len, 550 (off & 0x1fff) * 8, 551 (off & IP_MF)? "+" : ""); 552 } else if (off & IP_DF) 553 (void)printf(" (DF)"); 554 555 if (ip->ip_tos) 556 (void)printf(" [tos 0x%x]", (int)ip->ip_tos); 557 if (ip->ip_ttl <= 1) 558 (void)printf(" [ttl %d]", (int)ip->ip_ttl); 559 560 if (vflag) { 561 int sum; 562 char *sep = ""; 563 564 printf(" ("); 565 if (ip->ip_ttl > 1) { 566 (void)printf("%sttl %d", sep, (int)ip->ip_ttl); 567 sep = ", "; 568 } 569 if ((off & 0x3fff) == 0) { 570 (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id)); 571 sep = ", "; 572 } 573 if ((u_char *)ip + hlen <= snapend) { 574 sum = in_cksum(ip); 575 if (sum != 0) { 576 (void)printf("%sbad cksum %x!", sep, 577 ntohs(ip->ip_sum)); 578 sep = ", "; 579 } 580 } 581 if ((hlen -= sizeof(struct ip)) > 0) { 582 (void)printf("%soptlen=%d", sep, hlen); 583 ip_optprint((u_char *)(ip + 1), hlen); 584 } 585 printf(")"); 586 } 587} 588