print-ip.c revision 127675
117680Spst/* 239300Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2056896Sfenner * 2156896Sfenner * $FreeBSD: head/contrib/tcpdump/print-ip.c 127675 2004-03-31 14:57:24Z bms $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26127675Sbms "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.128.2.6 2004/03/24 09:01:39 guy Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2956896Sfenner#ifdef HAVE_CONFIG_H 3056896Sfenner#include "config.h" 3156896Sfenner#endif 3256896Sfenner 33127675Sbms#include <tcpdump-stdinc.h> 3417680Spst 3517680Spst#include <stdio.h> 3617680Spst#include <stdlib.h> 3717680Spst#include <string.h> 3817680Spst 3917680Spst#include "addrtoname.h" 4017680Spst#include "interface.h" 4117680Spst#include "extract.h" /* must come after interface.h */ 4217680Spst 4375118Sfenner#include "ip.h" 44127675Sbms#include "ipproto.h" 4575118Sfenner 4617680Spst/* 4717680Spst * print the recorded route in an IP RR, LSRR or SSRR option. 4817680Spst */ 4917680Spststatic void 5017680Spstip_printroute(const char *type, register const u_char *cp, u_int length) 5117680Spst{ 52127675Sbms register u_int ptr; 5317680Spst register u_int len; 5417680Spst 55127675Sbms if (length < 3) { 56127675Sbms printf(" [bad length %u]", length); 57127675Sbms return; 58127675Sbms } 5917680Spst printf(" %s{", type); 6017680Spst if ((length + 1) & 3) 61127675Sbms printf(" [bad length %u]", length); 62127675Sbms ptr = cp[2] - 1; 6317680Spst if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) 64127675Sbms printf(" [bad ptr %u]", cp[2]); 6517680Spst 6617680Spst type = ""; 6717680Spst for (len = 3; len < length; len += 4) { 6817680Spst if (ptr == len) 6917680Spst type = "#"; 7017680Spst printf("%s%s", type, ipaddr_string(&cp[len])); 7117680Spst type = " "; 7217680Spst } 7317680Spst printf("%s}", ptr == len? "#" : ""); 7417680Spst} 7517680Spst 76127675Sbms/* 77127675Sbms * If source-routing is present, return the final destination. 78127675Sbms * Otherwise, return IP destination. 79127675Sbms * 80127675Sbms * This is used for UDP and TCP pseudo-header in the checksum 81127675Sbms * calculation. 82127675Sbms */ 83127675Sbmsu_int32_t 84127675Sbmsip_finddst(const struct ip *ip) 85127675Sbms{ 86127675Sbms int length; 87127675Sbms int len; 88127675Sbms const u_char *cp; 89127675Sbms u_int32_t retval; 90127675Sbms 91127675Sbms cp = (const u_char *)(ip + 1); 92127675Sbms length = (IP_HL(ip) << 2) - sizeof(struct ip); 93127675Sbms 94127675Sbms for (; length > 0; cp += len, length -= len) { 95127675Sbms int tt; 96127675Sbms 97127675Sbms TCHECK(*cp); 98127675Sbms tt = *cp; 99127675Sbms if (tt == IPOPT_NOP || tt == IPOPT_EOL) 100127675Sbms len = 1; 101127675Sbms else { 102127675Sbms TCHECK(cp[1]); 103127675Sbms len = cp[1]; 104127675Sbms } 105127675Sbms if (len < 2) { 106127675Sbms return 0; 107127675Sbms } 108127675Sbms TCHECK2(*cp, len); 109127675Sbms switch (tt) { 110127675Sbms 111127675Sbms case IPOPT_SSRR: 112127675Sbms case IPOPT_LSRR: 113127675Sbms if (len < 7) 114127675Sbms return 0; 115127675Sbms memcpy(&retval, cp + len - 4, 4); 116127675Sbms return retval; 117127675Sbms } 118127675Sbms } 119127675Sbms return ip->ip_dst.s_addr; 120127675Sbms 121127675Sbmstrunc: 122127675Sbms return 0; 123127675Sbms} 124127675Sbms 12556896Sfennerstatic void 12656896Sfennerip_printts(register const u_char *cp, u_int length) 12756896Sfenner{ 128127675Sbms register u_int ptr; 129127675Sbms register u_int len; 13056896Sfenner int hoplen; 131127675Sbms const char *type; 13256896Sfenner 133127675Sbms if (length < 4) { 134127675Sbms printf("[bad length %d]", length); 135127675Sbms return; 136127675Sbms } 13756896Sfenner printf(" TS{"); 13856896Sfenner hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4; 13956896Sfenner if ((length - 4) & (hoplen-1)) 14056896Sfenner printf("[bad length %d]", length); 141127675Sbms ptr = cp[2] - 1; 142127675Sbms len = 0; 14356896Sfenner if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) 14456896Sfenner printf("[bad ptr %d]", cp[2]); 14556896Sfenner switch (cp[3]&0xF) { 14656896Sfenner case IPOPT_TS_TSONLY: 14756896Sfenner printf("TSONLY"); 14856896Sfenner break; 14956896Sfenner case IPOPT_TS_TSANDADDR: 15056896Sfenner printf("TS+ADDR"); 15156896Sfenner break; 15256896Sfenner /* 15356896Sfenner * prespecified should really be 3, but some ones might send 2 15456896Sfenner * instead, and the IPOPT_TS_PRESPEC constant can apparently 15556896Sfenner * have both values, so we have to hard-code it here. 15656896Sfenner */ 15756896Sfenner 15856896Sfenner case 2: 15956896Sfenner printf("PRESPEC2.0"); 16056896Sfenner break; 16156896Sfenner case 3: /* IPOPT_TS_PRESPEC */ 16256896Sfenner printf("PRESPEC"); 16356896Sfenner break; 164127675Sbms default: 16556896Sfenner printf("[bad ts type %d]", cp[3]&0xF); 16656896Sfenner goto done; 16756896Sfenner } 16856896Sfenner 16956896Sfenner type = " "; 17056896Sfenner for (len = 4; len < length; len += hoplen) { 17156896Sfenner if (ptr == len) 17256896Sfenner type = " ^ "; 17356896Sfenner printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]), 17456896Sfenner hoplen!=8 ? "" : ipaddr_string(&cp[len])); 17556896Sfenner type = " "; 17656896Sfenner } 17756896Sfenner 17856896Sfennerdone: 17956896Sfenner printf("%s", ptr == len ? " ^ " : ""); 18056896Sfenner 18156896Sfenner if (cp[3]>>4) 18256896Sfenner printf(" [%d hops not recorded]} ", cp[3]>>4); 18356896Sfenner else 18456896Sfenner printf("}"); 18556896Sfenner} 18656896Sfenner 18717680Spst/* 18817680Spst * print IP options. 18917680Spst */ 19017680Spststatic void 19117680Spstip_optprint(register const u_char *cp, u_int length) 19217680Spst{ 19317680Spst register u_int len; 19417680Spst 19517680Spst for (; length > 0; cp += len, length -= len) { 196127675Sbms int tt; 19717680Spst 198127675Sbms TCHECK(*cp); 199127675Sbms tt = *cp; 20075118Sfenner if (tt == IPOPT_NOP || tt == IPOPT_EOL) 20175118Sfenner len = 1; 20275118Sfenner else { 203127675Sbms TCHECK(cp[1]); 204127675Sbms len = cp[1]; 205127675Sbms if (len < 2) { 206127675Sbms printf("[|ip op len %d]", len); 20775118Sfenner return; 20875118Sfenner } 209127675Sbms TCHECK2(*cp, len); 21075118Sfenner } 21117680Spst switch (tt) { 21217680Spst 21317680Spst case IPOPT_EOL: 21417680Spst printf(" EOL"); 21517680Spst if (length > 1) 21617680Spst printf("-%d", length - 1); 21717680Spst return; 21817680Spst 21917680Spst case IPOPT_NOP: 22017680Spst printf(" NOP"); 22117680Spst break; 22217680Spst 22317680Spst case IPOPT_TS: 22456896Sfenner ip_printts(cp, len); 22517680Spst break; 22617680Spst 22756896Sfenner#ifndef IPOPT_SECURITY 22856896Sfenner#define IPOPT_SECURITY 130 22956896Sfenner#endif /* IPOPT_SECURITY */ 23017680Spst case IPOPT_SECURITY: 23117680Spst printf(" SECURITY{%d}", len); 23217680Spst break; 23317680Spst 23417680Spst case IPOPT_RR: 23517680Spst ip_printroute("RR", cp, len); 23617680Spst break; 23717680Spst 23817680Spst case IPOPT_SSRR: 23917680Spst ip_printroute("SSRR", cp, len); 24017680Spst break; 24117680Spst 24217680Spst case IPOPT_LSRR: 24317680Spst ip_printroute("LSRR", cp, len); 24417680Spst break; 24517680Spst 24656896Sfenner#ifndef IPOPT_RA 24756896Sfenner#define IPOPT_RA 148 /* router alert */ 24856896Sfenner#endif 24917691Spst case IPOPT_RA: 25056896Sfenner printf(" RA"); 25156896Sfenner if (len != 4) 25256896Sfenner printf("{%d}", len); 253127675Sbms else { 254127675Sbms TCHECK(cp[3]); 255127675Sbms if (cp[2] || cp[3]) 256127675Sbms printf("%d.%d", cp[2], cp[3]); 257127675Sbms } 25898527Sfenner break; 25917691Spst 26017680Spst default: 26117680Spst printf(" IPOPT-%d{%d}", cp[0], len); 26217680Spst break; 26317680Spst } 26417680Spst } 265127675Sbms return; 266127675Sbms 267127675Sbmstrunc: 268127675Sbms printf("[|ip]"); 26917680Spst} 27017680Spst 27117680Spst/* 27217680Spst * compute an IP header checksum. 27317680Spst * don't modifiy the packet. 27417680Spst */ 27556896Sfenneru_short 27698527Sfennerin_cksum(const u_short *addr, register u_int len, int csum) 27717680Spst{ 27856896Sfenner int nleft = len; 27956896Sfenner const u_short *w = addr; 28056896Sfenner u_short answer; 28156896Sfenner int sum = csum; 28217680Spst 283127675Sbms /* 28456896Sfenner * Our algorithm is simple, using a 32 bit accumulator (sum), 28556896Sfenner * we add sequential 16 bit words to it, and at the end, fold 28656896Sfenner * back all the carry bits from the top 16 bits into the lower 28756896Sfenner * 16 bits. 288127675Sbms */ 28956896Sfenner while (nleft > 1) { 29056896Sfenner sum += *w++; 29156896Sfenner nleft -= 2; 29256896Sfenner } 29356896Sfenner if (nleft == 1) 29456896Sfenner sum += htons(*(u_char *)w<<8); 29556896Sfenner 29617680Spst /* 29756896Sfenner * add back carry outs from top 16 bits to low 16 bits 29817680Spst */ 29956896Sfenner sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 30056896Sfenner sum += (sum >> 16); /* add carry */ 30156896Sfenner answer = ~sum; /* truncate to 16 bits */ 30256896Sfenner return (answer); 30317680Spst} 30417680Spst 30517680Spst/* 306127675Sbms * Given the host-byte-order value of the checksum field in a packet 307127675Sbms * header, and the network-byte-order computed checksum of the data 308127675Sbms * that the checksum covers (including the checksum itself), compute 309127675Sbms * what the checksum field *should* have been. 310127675Sbms */ 311127675Sbmsu_int16_t 312127675Sbmsin_cksum_shouldbe(u_int16_t sum, u_int16_t computed_sum) 313127675Sbms{ 314127675Sbms u_int32_t shouldbe; 315127675Sbms 316127675Sbms /* 317127675Sbms * The value that should have gone into the checksum field 318127675Sbms * is the negative of the value gotten by summing up everything 319127675Sbms * *but* the checksum field. 320127675Sbms * 321127675Sbms * We can compute that by subtracting the value of the checksum 322127675Sbms * field from the sum of all the data in the packet, and then 323127675Sbms * computing the negative of that value. 324127675Sbms * 325127675Sbms * "sum" is the value of the checksum field, and "computed_sum" 326127675Sbms * is the negative of the sum of all the data in the packets, 327127675Sbms * so that's -(-computed_sum - sum), or (sum + computed_sum). 328127675Sbms * 329127675Sbms * All the arithmetic in question is one's complement, so the 330127675Sbms * addition must include an end-around carry; we do this by 331127675Sbms * doing the arithmetic in 32 bits (with no sign-extension), 332127675Sbms * and then adding the upper 16 bits of the sum, which contain 333127675Sbms * the carry, to the lower 16 bits of the sum, and then do it 334127675Sbms * again in case *that* sum produced a carry. 335127675Sbms * 336127675Sbms * As RFC 1071 notes, the checksum can be computed without 337127675Sbms * byte-swapping the 16-bit words; summing 16-bit words 338127675Sbms * on a big-endian machine gives a big-endian checksum, which 339127675Sbms * can be directly stuffed into the big-endian checksum fields 340127675Sbms * in protocol headers, and summing words on a little-endian 341127675Sbms * machine gives a little-endian checksum, which must be 342127675Sbms * byte-swapped before being stuffed into a big-endian checksum 343127675Sbms * field. 344127675Sbms * 345127675Sbms * "computed_sum" is a network-byte-order value, so we must put 346127675Sbms * it in host byte order before subtracting it from the 347127675Sbms * host-byte-order value from the header; the adjusted checksum 348127675Sbms * will be in host byte order, which is what we'll return. 349127675Sbms */ 350127675Sbms shouldbe = sum; 351127675Sbms shouldbe += ntohs(computed_sum); 352127675Sbms shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); 353127675Sbms shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); 354127675Sbms return shouldbe; 355127675Sbms} 356127675Sbms 357127675Sbms#ifndef IP_MF 358127675Sbms#define IP_MF 0x2000 359127675Sbms#endif /* IP_MF */ 360127675Sbms#ifndef IP_DF 361127675Sbms#define IP_DF 0x4000 362127675Sbms#endif /* IP_DF */ 363127675Sbms#define IP_RES 0x8000 364127675Sbms 365127675Sbmsstatic struct tok ip_frag_values[] = { 366127675Sbms { IP_MF, "+" }, 367127675Sbms { IP_DF, "DF" }, 368127675Sbms { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */ 369127675Sbms { 0, NULL } 370127675Sbms}; 371127675Sbms 372127675Sbms/* 37317680Spst * print an IP datagram. 37417680Spst */ 37517680Spstvoid 37617680Spstip_print(register const u_char *bp, register u_int length) 37717680Spst{ 37817680Spst register const struct ip *ip; 37956896Sfenner register u_int hlen, len, len0, off; 380127675Sbms const u_char *ipend; 38117680Spst register const u_char *cp; 38256896Sfenner u_char nh; 38356896Sfenner int advance; 384111729Sfenner struct protoent *proto; 385127675Sbms u_int16_t sum, ip_sum; 38617680Spst 38717680Spst ip = (const struct ip *)bp; 388127675Sbms if (IP_V(ip) != 4) { /* print version if != 4 */ 389127675Sbms printf("IP%u ", IP_V(ip)); 390127675Sbms if (IP_V(ip) == 6) 391127675Sbms printf(", wrong link-layer encapsulation"); 392127675Sbms } 393127675Sbms else 394127675Sbms printf("IP "); 39517680Spst 39617680Spst if ((u_char *)(ip + 1) > snapend) { 39717680Spst printf("[|ip]"); 39817680Spst return; 39917680Spst } 40017680Spst if (length < sizeof (struct ip)) { 40117680Spst (void)printf("truncated-ip %d", length); 40217680Spst return; 40317680Spst } 40475118Sfenner hlen = IP_HL(ip) * 4; 40575118Sfenner if (hlen < sizeof (struct ip)) { 406127675Sbms (void)printf("bad-hlen %u", hlen); 40775118Sfenner return; 40875118Sfenner } 40917680Spst 410127675Sbms len = EXTRACT_16BITS(&ip->ip_len); 41117680Spst if (length < len) 412127675Sbms (void)printf("truncated-ip - %u bytes missing! ", 41317680Spst len - length); 414127675Sbms if (len < hlen) { 415127675Sbms (void)printf("bad-len %u", len); 416127675Sbms return; 417127675Sbms } 418127675Sbms 419127675Sbms /* 420127675Sbms * Cut off the snapshot length to the end of the IP payload. 421127675Sbms */ 422127675Sbms ipend = bp + len; 423127675Sbms if (ipend < snapend) 424127675Sbms snapend = ipend; 425127675Sbms 42617680Spst len -= hlen; 42756896Sfenner len0 = len; 42817680Spst 429127675Sbms off = EXTRACT_16BITS(&ip->ip_off); 430127675Sbms 431127675Sbms if (vflag) { 432127675Sbms (void)printf("(tos 0x%x", (int)ip->ip_tos); 433127675Sbms /* ECN bits */ 434127675Sbms if (ip->ip_tos & 0x03) { 435127675Sbms switch (ip->ip_tos & 0x03) { 436127675Sbms case 1: 437127675Sbms (void)printf(",ECT(1)"); 438127675Sbms break; 439127675Sbms case 2: 440127675Sbms (void)printf(",ECT(0)"); 441127675Sbms break; 442127675Sbms case 3: 443127675Sbms (void)printf(",CE"); 444127675Sbms } 445127675Sbms } 446127675Sbms 447127675Sbms if (ip->ip_ttl >= 1) 448127675Sbms (void)printf(", ttl %3u", ip->ip_ttl); 449127675Sbms 450127675Sbms /* 451127675Sbms * for the firewall guys, print id, offset. 452127675Sbms * On all but the last stick a "+" in the flags portion. 453127675Sbms * For unfragmented datagrams, note the don't fragment flag. 454127675Sbms */ 455127675Sbms 456127675Sbms (void)printf(", id %u, offset %u, flags [%s]", 457127675Sbms EXTRACT_16BITS(&ip->ip_id), 458127675Sbms (off & 0x1fff) * 8, 459127675Sbms bittok2str(ip_frag_values, "none", off & 0xe000 )); 460127675Sbms 461127675Sbms (void)printf(", length: %u", EXTRACT_16BITS(&ip->ip_len)); 462127675Sbms 463127675Sbms if ((hlen - sizeof(struct ip)) > 0) { 464127675Sbms (void)printf(", optlength: %u (", hlen - (u_int)sizeof(struct ip)); 465127675Sbms ip_optprint((u_char *)(ip + 1), hlen - sizeof(struct ip)); 466127675Sbms printf(" )"); 467127675Sbms } 468127675Sbms 469127675Sbms if ((u_char *)ip + hlen <= snapend) { 470127675Sbms sum = in_cksum((const u_short *)ip, hlen, 0); 471127675Sbms if (sum != 0) { 472127675Sbms ip_sum = EXTRACT_16BITS(&ip->ip_sum); 473127675Sbms (void)printf(", bad cksum %x (->%x)!", ip_sum, 474127675Sbms in_cksum_shouldbe(ip_sum, sum)); 475127675Sbms } 476127675Sbms } 477127675Sbms 478127675Sbms printf(") "); 479127675Sbms } 480127675Sbms 48117680Spst /* 48217680Spst * If this is fragment zero, hand it to the next higher 48317680Spst * level protocol. 48417680Spst */ 48517680Spst if ((off & 0x1fff) == 0) { 48617680Spst cp = (const u_char *)ip + hlen; 48756896Sfenner nh = ip->ip_p; 48817680Spst 48998527Sfenner if (nh != IPPROTO_TCP && nh != IPPROTO_UDP && 49098527Sfenner nh != IPPROTO_SCTP) { 49156896Sfenner (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src), 49256896Sfenner ipaddr_string(&ip->ip_dst)); 49356896Sfenner } 49456896Sfenneragain: 49556896Sfenner switch (nh) { 49656896Sfenner 49756896Sfenner case IPPROTO_AH: 49856896Sfenner nh = *cp; 499127675Sbms advance = ah_print(cp); 500127675Sbms if (advance <= 0) 501127675Sbms break; 50256896Sfenner cp += advance; 50356896Sfenner len -= advance; 50456896Sfenner goto again; 50556896Sfenner 50656896Sfenner case IPPROTO_ESP: 50756896Sfenner { 50898527Sfenner int enh, padlen; 50998527Sfenner advance = esp_print(cp, (const u_char *)ip, &enh, &padlen); 510127675Sbms if (advance <= 0) 511127675Sbms break; 51256896Sfenner cp += advance; 51398527Sfenner len -= advance + padlen; 51456896Sfenner nh = enh & 0xff; 51556896Sfenner goto again; 51656896Sfenner } 51756896Sfenner 51856896Sfenner case IPPROTO_IPCOMP: 51956896Sfenner { 52056896Sfenner int enh; 521127675Sbms advance = ipcomp_print(cp, &enh); 522127675Sbms if (advance <= 0) 523127675Sbms break; 52456896Sfenner cp += advance; 52556896Sfenner len -= advance; 52656896Sfenner nh = enh & 0xff; 52756896Sfenner goto again; 52856896Sfenner } 52956896Sfenner 53098527Sfenner case IPPROTO_SCTP: 531127675Sbms sctp_print(cp, (const u_char *)ip, len); 53298527Sfenner break; 53398527Sfenner 53417680Spst case IPPROTO_TCP: 53575118Sfenner tcp_print(cp, len, (const u_char *)ip, (off &~ 0x6000)); 53617680Spst break; 53717680Spst 53817680Spst case IPPROTO_UDP: 53975118Sfenner udp_print(cp, len, (const u_char *)ip, (off &~ 0x6000)); 54017680Spst break; 54117680Spst 54217680Spst case IPPROTO_ICMP: 543127675Sbms /* pass on the MF bit plus the offset to detect fragments */ 544127675Sbms icmp_print(cp, len, (const u_char *)ip, (off & 0x3fff)); 54517680Spst break; 54617680Spst 54717680Spst case IPPROTO_IGRP: 54817680Spst igrp_print(cp, len, (const u_char *)ip); 54917680Spst break; 55017680Spst 55117680Spst case IPPROTO_ND: 55217680Spst (void)printf(" nd %d", len); 55317680Spst break; 55417680Spst 55517680Spst case IPPROTO_EGP: 556127675Sbms egp_print(cp); 55717680Spst break; 55817680Spst 55917680Spst case IPPROTO_OSPF: 56017680Spst ospf_print(cp, len, (const u_char *)ip); 56117680Spst break; 56217680Spst 56317680Spst case IPPROTO_IGMP: 56498527Sfenner igmp_print(cp, len); 56517680Spst break; 56617680Spst 567127675Sbms case IPPROTO_IPV4: 56839300Sfenner /* DVMRP multicast tunnel (ip-in-ip encapsulation) */ 56917680Spst ip_print(cp, len); 57017680Spst if (! vflag) { 57198527Sfenner printf(" (ipip-proto-4)"); 57217680Spst return; 57317680Spst } 57417680Spst break; 57517680Spst 57656896Sfenner#ifdef INET6 577127675Sbms case IPPROTO_IPV6: 57856896Sfenner /* ip6-in-ip encapsulation */ 57956896Sfenner ip6_print(cp, len); 58056896Sfenner break; 58156896Sfenner#endif /*INET6*/ 58256896Sfenner 583127675Sbms case IPPROTO_RSVP: 584127675Sbms rsvp_print(cp, len); 585127675Sbms break; 58656896Sfenner 58726183Sfenner case IPPROTO_GRE: 58826183Sfenner /* do it */ 58926183Sfenner gre_print(cp, len); 59098527Sfenner break; 59126183Sfenner 59256896Sfenner case IPPROTO_MOBILE: 59356896Sfenner mobile_print(cp, len); 59456896Sfenner break; 59556896Sfenner 59656896Sfenner case IPPROTO_PIM: 59756896Sfenner pim_print(cp, len); 59856896Sfenner break; 59956896Sfenner 60075118Sfenner case IPPROTO_VRRP: 60175118Sfenner vrrp_print(cp, len, ip->ip_ttl); 60275118Sfenner break; 60375118Sfenner 60417680Spst default: 605111729Sfenner if ((proto = getprotobynumber(nh)) != NULL) 606111729Sfenner (void)printf(" %s", proto->p_name); 607111729Sfenner else 608111729Sfenner (void)printf(" ip-proto-%d", nh); 609111729Sfenner printf(" %d", len); 61017680Spst break; 61117680Spst } 612127675Sbms } else { 613127675Sbms /* Ultra quiet now means that all this stuff should be suppressed */ 614127675Sbms if (qflag > 1) return; 61556896Sfenner 616127675Sbms /* 617127675Sbms * if this isn't the first frag, we're missing the 618127675Sbms * next level protocol header. print the ip addr 619127675Sbms * and the protocol. 620127675Sbms */ 621127675Sbms if (off & 0x1fff) { 622127675Sbms (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), 623127675Sbms ipaddr_string(&ip->ip_dst)); 624127675Sbms if ((proto = getprotobynumber(ip->ip_p)) != NULL) 625127675Sbms (void)printf(" %s", proto->p_name); 626127675Sbms else 627127675Sbms (void)printf(" ip-proto-%d", ip->ip_p); 628127675Sbms } 62956896Sfenner } 63017680Spst} 63175118Sfenner 63275118Sfennervoid 63375118SfenneripN_print(register const u_char *bp, register u_int length) 63475118Sfenner{ 63575118Sfenner struct ip *ip, hdr; 63675118Sfenner 63775118Sfenner ip = (struct ip *)bp; 63875118Sfenner if (length < 4) { 63975118Sfenner (void)printf("truncated-ip %d", length); 64075118Sfenner return; 64175118Sfenner } 64275118Sfenner memcpy (&hdr, (char *)ip, 4); 64375118Sfenner switch (IP_V(&hdr)) { 64475118Sfenner case 4: 64598527Sfenner ip_print (bp, length); 64698527Sfenner return; 64775118Sfenner#ifdef INET6 64875118Sfenner case 6: 64998527Sfenner ip6_print (bp, length); 65098527Sfenner return; 65175118Sfenner#endif 65275118Sfenner default: 65398527Sfenner (void)printf("unknown ip %d", IP_V(&hdr)); 65498527Sfenner return; 65575118Sfenner } 65675118Sfenner} 657127675Sbms 658127675Sbms 659127675Sbms 660