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$ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.159 2007-09-14 01:29:28 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 46146778Ssamstruct tok ip_option_values[] = { 47146778Ssam { IPOPT_EOL, "EOL" }, 48146778Ssam { IPOPT_NOP, "NOP" }, 49146778Ssam { IPOPT_TS, "timestamp" }, 50146778Ssam { IPOPT_SECURITY, "security" }, 51146778Ssam { IPOPT_RR, "RR" }, 52146778Ssam { IPOPT_SSRR, "SSRR" }, 53146778Ssam { IPOPT_LSRR, "LSRR" }, 54146778Ssam { IPOPT_RA, "RA" }, 55172686Smlaier { IPOPT_RFC1393, "traceroute" }, 56146778Ssam { 0, NULL } 57146778Ssam}; 58146778Ssam 5917680Spst/* 6017680Spst * print the recorded route in an IP RR, LSRR or SSRR option. 6117680Spst */ 6217680Spststatic void 63146778Ssamip_printroute(register const u_char *cp, u_int length) 6417680Spst{ 65127675Sbms register u_int ptr; 6617680Spst register u_int len; 6717680Spst 68127675Sbms if (length < 3) { 69127675Sbms printf(" [bad length %u]", length); 70127675Sbms return; 71127675Sbms } 7217680Spst if ((length + 1) & 3) 73127675Sbms printf(" [bad length %u]", length); 74127675Sbms ptr = cp[2] - 1; 7517680Spst if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) 76127675Sbms printf(" [bad ptr %u]", cp[2]); 7717680Spst 7817680Spst for (len = 3; len < length; len += 4) { 79172686Smlaier printf(" %s", ipaddr_string(&cp[len])); 80146778Ssam if (ptr > len) 81172686Smlaier printf(","); 8217680Spst } 8317680Spst} 8417680Spst 85127675Sbms/* 86146778Ssam * If source-routing is present and valid, return the final destination. 87127675Sbms * Otherwise, return IP destination. 88127675Sbms * 89127675Sbms * This is used for UDP and TCP pseudo-header in the checksum 90127675Sbms * calculation. 91127675Sbms */ 92235530Sdelphijstatic u_int32_t 93127675Sbmsip_finddst(const struct ip *ip) 94127675Sbms{ 95127675Sbms int length; 96127675Sbms int len; 97127675Sbms const u_char *cp; 98127675Sbms u_int32_t retval; 99127675Sbms 100127675Sbms cp = (const u_char *)(ip + 1); 101127675Sbms length = (IP_HL(ip) << 2) - sizeof(struct ip); 102127675Sbms 103127675Sbms for (; length > 0; cp += len, length -= len) { 104127675Sbms int tt; 105127675Sbms 106127675Sbms TCHECK(*cp); 107127675Sbms tt = *cp; 108146778Ssam if (tt == IPOPT_EOL) 109146778Ssam break; 110146778Ssam else if (tt == IPOPT_NOP) 111127675Sbms len = 1; 112127675Sbms else { 113127675Sbms TCHECK(cp[1]); 114127675Sbms len = cp[1]; 115146778Ssam if (len < 2) 116146778Ssam break; 117127675Sbms } 118127675Sbms TCHECK2(*cp, len); 119127675Sbms switch (tt) { 120127675Sbms 121127675Sbms case IPOPT_SSRR: 122127675Sbms case IPOPT_LSRR: 123127675Sbms if (len < 7) 124146778Ssam break; 125127675Sbms memcpy(&retval, cp + len - 4, 4); 126127675Sbms return retval; 127127675Sbms } 128127675Sbms } 129127675Sbmstrunc: 130146778Ssam memcpy(&retval, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 131146778Ssam return retval; 132127675Sbms} 133127675Sbms 134235530Sdelphij/* 135235530Sdelphij * Compute a V4-style checksum by building a pseudoheader. 136235530Sdelphij */ 137235530Sdelphijint 138235530Sdelphijnextproto4_cksum(const struct ip *ip, const u_int8_t *data, 139235530Sdelphij u_int len, u_int next_proto) 140235530Sdelphij{ 141235530Sdelphij struct phdr { 142235530Sdelphij u_int32_t src; 143235530Sdelphij u_int32_t dst; 144235530Sdelphij u_char mbz; 145235530Sdelphij u_char proto; 146235530Sdelphij u_int16_t len; 147235530Sdelphij } ph; 148235530Sdelphij struct cksum_vec vec[2]; 149235530Sdelphij 150235530Sdelphij /* pseudo-header.. */ 151235530Sdelphij ph.len = htons((u_int16_t)len); 152235530Sdelphij ph.mbz = 0; 153235530Sdelphij ph.proto = next_proto; 154235530Sdelphij memcpy(&ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); 155235530Sdelphij if (IP_HL(ip) == 5) 156235530Sdelphij memcpy(&ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); 157235530Sdelphij else 158235530Sdelphij ph.dst = ip_finddst(ip); 159235530Sdelphij 160235530Sdelphij vec[0].ptr = (const u_int8_t *)(void *)&ph; 161235530Sdelphij vec[0].len = sizeof(ph); 162235530Sdelphij vec[1].ptr = data; 163235530Sdelphij vec[1].len = len; 164235530Sdelphij return (in_cksum(vec, 2)); 165235530Sdelphij} 166235530Sdelphij 16756896Sfennerstatic void 16856896Sfennerip_printts(register const u_char *cp, u_int length) 16956896Sfenner{ 170127675Sbms register u_int ptr; 171127675Sbms register u_int len; 17256896Sfenner int hoplen; 173127675Sbms const char *type; 17456896Sfenner 175127675Sbms if (length < 4) { 176172686Smlaier printf("[bad length %u]", length); 177127675Sbms return; 178127675Sbms } 17956896Sfenner printf(" TS{"); 18056896Sfenner hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4; 18156896Sfenner if ((length - 4) & (hoplen-1)) 182172686Smlaier printf("[bad length %u]", length); 183127675Sbms ptr = cp[2] - 1; 184127675Sbms len = 0; 18556896Sfenner if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) 186172686Smlaier printf("[bad ptr %u]", cp[2]); 18756896Sfenner switch (cp[3]&0xF) { 18856896Sfenner case IPOPT_TS_TSONLY: 18956896Sfenner printf("TSONLY"); 19056896Sfenner break; 19156896Sfenner case IPOPT_TS_TSANDADDR: 19256896Sfenner printf("TS+ADDR"); 19356896Sfenner break; 19456896Sfenner /* 19556896Sfenner * prespecified should really be 3, but some ones might send 2 19656896Sfenner * instead, and the IPOPT_TS_PRESPEC constant can apparently 19756896Sfenner * have both values, so we have to hard-code it here. 19856896Sfenner */ 19956896Sfenner 20056896Sfenner case 2: 20156896Sfenner printf("PRESPEC2.0"); 20256896Sfenner break; 20356896Sfenner case 3: /* IPOPT_TS_PRESPEC */ 20456896Sfenner printf("PRESPEC"); 20556896Sfenner break; 206127675Sbms default: 20756896Sfenner printf("[bad ts type %d]", cp[3]&0xF); 20856896Sfenner goto done; 20956896Sfenner } 21056896Sfenner 21156896Sfenner type = " "; 21256896Sfenner for (len = 4; len < length; len += hoplen) { 21356896Sfenner if (ptr == len) 21456896Sfenner type = " ^ "; 21556896Sfenner printf("%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]), 21656896Sfenner hoplen!=8 ? "" : ipaddr_string(&cp[len])); 21756896Sfenner type = " "; 21856896Sfenner } 21956896Sfenner 22056896Sfennerdone: 22156896Sfenner printf("%s", ptr == len ? " ^ " : ""); 22256896Sfenner 22356896Sfenner if (cp[3]>>4) 22456896Sfenner printf(" [%d hops not recorded]} ", cp[3]>>4); 22556896Sfenner else 22656896Sfenner printf("}"); 22756896Sfenner} 22856896Sfenner 22917680Spst/* 23017680Spst * print IP options. 23117680Spst */ 23217680Spststatic void 23317680Spstip_optprint(register const u_char *cp, u_int length) 23417680Spst{ 235146778Ssam register u_int option_len; 236172686Smlaier const char *sep = ""; 23717680Spst 238146778Ssam for (; length > 0; cp += option_len, length -= option_len) { 239146778Ssam u_int option_code; 24017680Spst 241172686Smlaier printf("%s", sep); 242172686Smlaier sep = ","; 243172686Smlaier 244127675Sbms TCHECK(*cp); 245146778Ssam option_code = *cp; 246146778Ssam 247172686Smlaier printf("%s", 248172686Smlaier tok2str(ip_option_values,"unknown %u",option_code)); 249172686Smlaier 250146778Ssam if (option_code == IPOPT_NOP || 251146778Ssam option_code == IPOPT_EOL) 252146778Ssam option_len = 1; 253146778Ssam 25475118Sfenner else { 255127675Sbms TCHECK(cp[1]); 256172686Smlaier option_len = cp[1]; 257172686Smlaier if (option_len < 2) { 258172686Smlaier printf(" [bad length %u]", option_len); 259172686Smlaier return; 260172686Smlaier } 26175118Sfenner } 26217680Spst 263172686Smlaier if (option_len > length) { 264172686Smlaier printf(" [bad length %u]", option_len); 265172686Smlaier return; 266172686Smlaier } 267146778Ssam 268146778Ssam TCHECK2(*cp, option_len); 269146778Ssam 270146778Ssam switch (option_code) { 27117680Spst case IPOPT_EOL: 27217680Spst return; 27317680Spst 27417680Spst case IPOPT_TS: 275146778Ssam ip_printts(cp, option_len); 27617680Spst break; 27717680Spst 278146778Ssam case IPOPT_RR: /* fall through */ 27917680Spst case IPOPT_SSRR: 28017680Spst case IPOPT_LSRR: 281172686Smlaier ip_printroute(cp, option_len); 28217680Spst break; 28317680Spst 28417691Spst case IPOPT_RA: 285172686Smlaier if (option_len < 4) { 286172686Smlaier printf(" [bad length %u]", option_len); 287172686Smlaier break; 288172686Smlaier } 289146778Ssam TCHECK(cp[3]); 290146778Ssam if (EXTRACT_16BITS(&cp[2]) != 0) 291172686Smlaier printf(" value %u", EXTRACT_16BITS(&cp[2])); 29298527Sfenner break; 29317691Spst 294146778Ssam case IPOPT_NOP: /* nothing to print - fall through */ 295146778Ssam case IPOPT_SECURITY: 29617680Spst default: 29717680Spst break; 29817680Spst } 29917680Spst } 300127675Sbms return; 301127675Sbms 302127675Sbmstrunc: 303127675Sbms printf("[|ip]"); 30417680Spst} 30517680Spst 306127675Sbms#define IP_RES 0x8000 307127675Sbms 308127675Sbmsstatic struct tok ip_frag_values[] = { 309127675Sbms { IP_MF, "+" }, 310127675Sbms { IP_DF, "DF" }, 311127675Sbms { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */ 312127675Sbms { 0, NULL } 313127675Sbms}; 314127675Sbms 315146778Ssamstruct ip_print_demux_state { 316146778Ssam const struct ip *ip; 317146778Ssam const u_char *cp; 318146778Ssam u_int len, off; 319146778Ssam u_char nh; 320146778Ssam int advance; 321146778Ssam}; 322146778Ssam 323146778Ssamstatic void 324146778Ssamip_print_demux(netdissect_options *ndo, 325146778Ssam struct ip_print_demux_state *ipds) 326146778Ssam{ 327146778Ssam struct protoent *proto; 328235530Sdelphij struct cksum_vec vec[1]; 329146778Ssam 330146778Ssamagain: 331146778Ssam switch (ipds->nh) { 332146778Ssam 333146778Ssam case IPPROTO_AH: 334146778Ssam ipds->nh = *ipds->cp; 335146778Ssam ipds->advance = ah_print(ipds->cp); 336146778Ssam if (ipds->advance <= 0) 337146778Ssam break; 338146778Ssam ipds->cp += ipds->advance; 339146778Ssam ipds->len -= ipds->advance; 340146778Ssam goto again; 341146778Ssam 342146778Ssam case IPPROTO_ESP: 343146778Ssam { 344146778Ssam int enh, padlen; 345146778Ssam ipds->advance = esp_print(ndo, ipds->cp, ipds->len, 346146778Ssam (const u_char *)ipds->ip, 347146778Ssam &enh, &padlen); 348146778Ssam if (ipds->advance <= 0) 349146778Ssam break; 350146778Ssam ipds->cp += ipds->advance; 351146778Ssam ipds->len -= ipds->advance + padlen; 352146778Ssam ipds->nh = enh & 0xff; 353146778Ssam goto again; 354146778Ssam } 355241235Sdelphij 356146778Ssam case IPPROTO_IPCOMP: 357146778Ssam { 358146778Ssam int enh; 359146778Ssam ipds->advance = ipcomp_print(ipds->cp, &enh); 360146778Ssam if (ipds->advance <= 0) 361146778Ssam break; 362146778Ssam ipds->cp += ipds->advance; 363146778Ssam ipds->len -= ipds->advance; 364146778Ssam ipds->nh = enh & 0xff; 365146778Ssam goto again; 366146778Ssam } 367146778Ssam 368146778Ssam case IPPROTO_SCTP: 369146778Ssam sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len); 370146778Ssam break; 371162021Ssam 372162021Ssam case IPPROTO_DCCP: 373162021Ssam dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len); 374162021Ssam break; 375241235Sdelphij 376146778Ssam case IPPROTO_TCP: 377172686Smlaier /* pass on the MF bit plus the offset to detect fragments */ 378146778Ssam tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, 379172686Smlaier ipds->off & (IP_MF|IP_OFFMASK)); 380146778Ssam break; 381241235Sdelphij 382146778Ssam case IPPROTO_UDP: 383172686Smlaier /* pass on the MF bit plus the offset to detect fragments */ 384146778Ssam udp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, 385172686Smlaier ipds->off & (IP_MF|IP_OFFMASK)); 386146778Ssam break; 387241235Sdelphij 388146778Ssam case IPPROTO_ICMP: 389146778Ssam /* pass on the MF bit plus the offset to detect fragments */ 390146778Ssam icmp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, 391172686Smlaier ipds->off & (IP_MF|IP_OFFMASK)); 392146778Ssam break; 393241235Sdelphij 394146778Ssam case IPPROTO_PIGP: 395146778Ssam /* 396146778Ssam * XXX - the current IANA protocol number assignments 397146778Ssam * page lists 9 as "any private interior gateway 398146778Ssam * (used by Cisco for their IGRP)" and 88 as 399146778Ssam * "EIGRP" from Cisco. 400146778Ssam * 401146778Ssam * Recent BSD <netinet/in.h> headers define 402146778Ssam * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88. 403146778Ssam * We define IP_PROTO_PIGP as 9 and 404146778Ssam * IP_PROTO_EIGRP as 88; those names better 405146778Ssam * match was the current protocol number 406146778Ssam * assignments say. 407146778Ssam */ 408146778Ssam igrp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip); 409146778Ssam break; 410241235Sdelphij 411146778Ssam case IPPROTO_EIGRP: 412146778Ssam eigrp_print(ipds->cp, ipds->len); 413146778Ssam break; 414241235Sdelphij 415146778Ssam case IPPROTO_ND: 416146778Ssam ND_PRINT((ndo, " nd %d", ipds->len)); 417146778Ssam break; 418146778Ssam 419146778Ssam case IPPROTO_EGP: 420146778Ssam egp_print(ipds->cp, ipds->len); 421146778Ssam break; 422146778Ssam 423146778Ssam case IPPROTO_OSPF: 424146778Ssam ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip); 425146778Ssam break; 426146778Ssam 427146778Ssam case IPPROTO_IGMP: 428146778Ssam igmp_print(ipds->cp, ipds->len); 429146778Ssam break; 430146778Ssam 431146778Ssam case IPPROTO_IPV4: 432146778Ssam /* DVMRP multicast tunnel (ip-in-ip encapsulation) */ 433235530Sdelphij ip_print(ndo, ipds->cp, ipds->len); 434146778Ssam if (! vflag) { 435146778Ssam ND_PRINT((ndo, " (ipip-proto-4)")); 436146778Ssam return; 437146778Ssam } 438146778Ssam break; 439241235Sdelphij 440146778Ssam#ifdef INET6 441146778Ssam case IPPROTO_IPV6: 442146778Ssam /* ip6-in-ip encapsulation */ 443235530Sdelphij ip6_print(ndo, ipds->cp, ipds->len); 444146778Ssam break; 445146778Ssam#endif /*INET6*/ 446146778Ssam 447146778Ssam case IPPROTO_RSVP: 448146778Ssam rsvp_print(ipds->cp, ipds->len); 449146778Ssam break; 450146778Ssam 451146778Ssam case IPPROTO_GRE: 452146778Ssam /* do it */ 453146778Ssam gre_print(ipds->cp, ipds->len); 454146778Ssam break; 455146778Ssam 456146778Ssam case IPPROTO_MOBILE: 457146778Ssam mobile_print(ipds->cp, ipds->len); 458146778Ssam break; 459146778Ssam 460146778Ssam case IPPROTO_PIM: 461235530Sdelphij vec[0].ptr = ipds->cp; 462235530Sdelphij vec[0].len = ipds->len; 463235530Sdelphij pim_print(ipds->cp, ipds->len, in_cksum(vec, 1)); 464146778Ssam break; 465146778Ssam 466146778Ssam case IPPROTO_VRRP: 467235530Sdelphij if (packettype == PT_CARP) { 468235530Sdelphij if (vflag) 469235530Sdelphij (void)printf("carp %s > %s: ", 470235530Sdelphij ipaddr_string(&ipds->ip->ip_src), 471235530Sdelphij ipaddr_string(&ipds->ip->ip_dst)); 472235530Sdelphij carp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl); 473235530Sdelphij } else { 474235530Sdelphij if (vflag) 475235530Sdelphij (void)printf("vrrp %s > %s: ", 476235530Sdelphij ipaddr_string(&ipds->ip->ip_src), 477235530Sdelphij ipaddr_string(&ipds->ip->ip_dst)); 478235530Sdelphij vrrp_print(ipds->cp, ipds->len, ipds->ip->ip_ttl); 479235530Sdelphij } 480146778Ssam break; 481146778Ssam 482147904Ssam case IPPROTO_PGM: 483147904Ssam pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip); 484147904Ssam break; 485147904Ssam 486263086Sglebius#if defined(HAVE_NET_PFVAR_H) 487241221Sglebius case IPPROTO_PFSYNC: 488241221Sglebius pfsync_ip_print(ipds->cp, ipds->len); 489241221Sglebius break; 490263086Sglebius#endif 491241221Sglebius 492146778Ssam default: 493241235Sdelphij if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL) 494146778Ssam ND_PRINT((ndo, " %s", proto->p_name)); 495146778Ssam else 496146778Ssam ND_PRINT((ndo, " ip-proto-%d", ipds->nh)); 497146778Ssam ND_PRINT((ndo, " %d", ipds->len)); 498146778Ssam break; 499146778Ssam } 500146778Ssam} 501241235Sdelphij 502146778Ssamvoid 503146778Ssamip_print_inner(netdissect_options *ndo, 504146778Ssam const u_char *bp, 505146778Ssam u_int length, u_int nh, 506146778Ssam const u_char *bp2) 507146778Ssam{ 508146778Ssam struct ip_print_demux_state ipd; 509146778Ssam 510146778Ssam ipd.ip = (const struct ip *)bp2; 511146778Ssam ipd.cp = bp; 512146778Ssam ipd.len = length; 513146778Ssam ipd.off = 0; 514146778Ssam ipd.nh = nh; 515146778Ssam ipd.advance = 0; 516146778Ssam 517146778Ssam ip_print_demux(ndo, &ipd); 518146778Ssam} 519146778Ssam 520146778Ssam 521127675Sbms/* 52217680Spst * print an IP datagram. 52317680Spst */ 52417680Spstvoid 525146778Ssamip_print(netdissect_options *ndo, 526146778Ssam const u_char *bp, 527146778Ssam u_int length) 52817680Spst{ 529146778Ssam struct ip_print_demux_state ipd; 530146778Ssam struct ip_print_demux_state *ipds=&ipd; 531127675Sbms const u_char *ipend; 532146778Ssam u_int hlen; 533235530Sdelphij struct cksum_vec vec[1]; 534146778Ssam u_int16_t sum, ip_sum; 535111729Sfenner struct protoent *proto; 53617680Spst 537146778Ssam ipds->ip = (const struct ip *)bp; 538146778Ssam if (IP_V(ipds->ip) != 4) { /* print version if != 4 */ 539146778Ssam printf("IP%u ", IP_V(ipds->ip)); 540146778Ssam if (IP_V(ipds->ip) == 6) 541127675Sbms printf(", wrong link-layer encapsulation"); 542127675Sbms } 543146778Ssam else if (!eflag) 544127675Sbms printf("IP "); 54517680Spst 546235530Sdelphij if ((u_char *)(ipds->ip + 1) > ndo->ndo_snapend) { 54717680Spst printf("[|ip]"); 54817680Spst return; 54917680Spst } 55017680Spst if (length < sizeof (struct ip)) { 551146778Ssam (void)printf("truncated-ip %u", length); 55217680Spst return; 55317680Spst } 554146778Ssam hlen = IP_HL(ipds->ip) * 4; 55575118Sfenner if (hlen < sizeof (struct ip)) { 556127675Sbms (void)printf("bad-hlen %u", hlen); 55775118Sfenner return; 55875118Sfenner } 55917680Spst 560146778Ssam ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len); 561146778Ssam if (length < ipds->len) 562127675Sbms (void)printf("truncated-ip - %u bytes missing! ", 563146778Ssam ipds->len - length); 564146778Ssam if (ipds->len < hlen) { 565146778Ssam#ifdef GUESS_TSO 566146778Ssam if (ipds->len) { 567146778Ssam (void)printf("bad-len %u", ipds->len); 568146778Ssam return; 569146778Ssam } 570146778Ssam else { 571146778Ssam /* we guess that it is a TSO send */ 572146778Ssam ipds->len = length; 573146778Ssam } 574146778Ssam#else 575146778Ssam (void)printf("bad-len %u", ipds->len); 576146778Ssam return; 577146778Ssam#endif /* GUESS_TSO */ 578127675Sbms } 579127675Sbms 580127675Sbms /* 581127675Sbms * Cut off the snapshot length to the end of the IP payload. 582127675Sbms */ 583146778Ssam ipend = bp + ipds->len; 584235530Sdelphij if (ipend < ndo->ndo_snapend) 585235530Sdelphij ndo->ndo_snapend = ipend; 586127675Sbms 587146778Ssam ipds->len -= hlen; 58817680Spst 589146778Ssam ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off); 590127675Sbms 591127675Sbms if (vflag) { 592146778Ssam (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos); 593127675Sbms /* ECN bits */ 594146778Ssam if (ipds->ip->ip_tos & 0x03) { 595146778Ssam switch (ipds->ip->ip_tos & 0x03) { 596127675Sbms case 1: 597127675Sbms (void)printf(",ECT(1)"); 598127675Sbms break; 599127675Sbms case 2: 600127675Sbms (void)printf(",ECT(0)"); 601127675Sbms break; 602127675Sbms case 3: 603127675Sbms (void)printf(",CE"); 604127675Sbms } 605127675Sbms } 606127675Sbms 607146778Ssam if (ipds->ip->ip_ttl >= 1) 608241235Sdelphij (void)printf(", ttl %u", ipds->ip->ip_ttl); 609127675Sbms 610127675Sbms /* 611127675Sbms * for the firewall guys, print id, offset. 612127675Sbms * On all but the last stick a "+" in the flags portion. 613127675Sbms * For unfragmented datagrams, note the don't fragment flag. 614127675Sbms */ 615127675Sbms 616172686Smlaier (void)printf(", id %u, offset %u, flags [%s], proto %s (%u)", 617146778Ssam EXTRACT_16BITS(&ipds->ip->ip_id), 618146778Ssam (ipds->off & 0x1fff) * 8, 619172686Smlaier bittok2str(ip_frag_values, "none", ipds->off&0xe000), 620146778Ssam tok2str(ipproto_values,"unknown",ipds->ip->ip_p), 621146778Ssam ipds->ip->ip_p); 622127675Sbms 623172686Smlaier (void)printf(", length %u", EXTRACT_16BITS(&ipds->ip->ip_len)); 624127675Sbms 625127675Sbms if ((hlen - sizeof(struct ip)) > 0) { 626172686Smlaier printf(", options ("); 627146778Ssam ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip)); 628172686Smlaier printf(")"); 629127675Sbms } 630127675Sbms 631235530Sdelphij if (!Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) { 632235530Sdelphij vec[0].ptr = (const u_int8_t *)(void *)ipds->ip; 633235530Sdelphij vec[0].len = hlen; 634235530Sdelphij sum = in_cksum(vec, 1); 635127675Sbms if (sum != 0) { 636146778Ssam ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum); 637127675Sbms (void)printf(", bad cksum %x (->%x)!", ip_sum, 638127675Sbms in_cksum_shouldbe(ip_sum, sum)); 639127675Sbms } 640127675Sbms } 641127675Sbms 642190207Srpaulo printf(")\n "); 643127675Sbms } 644127675Sbms 64517680Spst /* 64617680Spst * If this is fragment zero, hand it to the next higher 64717680Spst * level protocol. 64817680Spst */ 649146778Ssam if ((ipds->off & 0x1fff) == 0) { 650146778Ssam ipds->cp = (const u_char *)ipds->ip + hlen; 651146778Ssam ipds->nh = ipds->ip->ip_p; 65217680Spst 653146778Ssam if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP && 654162021Ssam ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) { 655146778Ssam (void)printf("%s > %s: ", 656146778Ssam ipaddr_string(&ipds->ip->ip_src), 657146778Ssam ipaddr_string(&ipds->ip->ip_dst)); 65856896Sfenner } 659146778Ssam ip_print_demux(ndo, ipds); 660127675Sbms } else { 661127675Sbms /* Ultra quiet now means that all this stuff should be suppressed */ 662127675Sbms if (qflag > 1) return; 66356896Sfenner 664127675Sbms /* 665127675Sbms * if this isn't the first frag, we're missing the 666127675Sbms * next level protocol header. print the ip addr 667127675Sbms * and the protocol. 668127675Sbms */ 669146778Ssam if (ipds->off & 0x1fff) { 670146778Ssam (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src), 671146778Ssam ipaddr_string(&ipds->ip->ip_dst)); 672241235Sdelphij if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL) 673127675Sbms (void)printf(" %s", proto->p_name); 674127675Sbms else 675146778Ssam (void)printf(" ip-proto-%d", ipds->ip->ip_p); 676241235Sdelphij } 67756896Sfenner } 67817680Spst} 67975118Sfenner 68075118Sfennervoid 68175118SfenneripN_print(register const u_char *bp, register u_int length) 68275118Sfenner{ 68375118Sfenner struct ip *ip, hdr; 68475118Sfenner 68575118Sfenner ip = (struct ip *)bp; 68675118Sfenner if (length < 4) { 68775118Sfenner (void)printf("truncated-ip %d", length); 68875118Sfenner return; 68975118Sfenner } 69075118Sfenner memcpy (&hdr, (char *)ip, 4); 69175118Sfenner switch (IP_V(&hdr)) { 69275118Sfenner case 4: 693146778Ssam ip_print (gndo, bp, length); 69498527Sfenner return; 69575118Sfenner#ifdef INET6 69675118Sfenner case 6: 697235530Sdelphij ip6_print (gndo, bp, length); 69898527Sfenner return; 69975118Sfenner#endif 70075118Sfenner default: 70198527Sfenner (void)printf("unknown ip %d", IP_V(&hdr)); 70298527Sfenner return; 70375118Sfenner } 70475118Sfenner} 705127675Sbms 706146778Ssam/* 707146778Ssam * Local Variables: 708146778Ssam * c-style: whitesmith 709146778Ssam * c-basic-offset: 8 710146778Ssam * End: 711146778Ssam */ 712127675Sbms 713127675Sbms 714