print-ip.c revision 241235
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 241235 2012-10-05 20:19:28Z delphij $ 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 486241221Sglebius case IPPROTO_PFSYNC: 487241221Sglebius pfsync_ip_print(ipds->cp, ipds->len); 488241221Sglebius break; 489241221Sglebius 490146778Ssam default: 491241235Sdelphij if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL) 492146778Ssam ND_PRINT((ndo, " %s", proto->p_name)); 493146778Ssam else 494146778Ssam ND_PRINT((ndo, " ip-proto-%d", ipds->nh)); 495146778Ssam ND_PRINT((ndo, " %d", ipds->len)); 496146778Ssam break; 497146778Ssam } 498146778Ssam} 499241235Sdelphij 500146778Ssamvoid 501146778Ssamip_print_inner(netdissect_options *ndo, 502146778Ssam const u_char *bp, 503146778Ssam u_int length, u_int nh, 504146778Ssam const u_char *bp2) 505146778Ssam{ 506146778Ssam struct ip_print_demux_state ipd; 507146778Ssam 508146778Ssam ipd.ip = (const struct ip *)bp2; 509146778Ssam ipd.cp = bp; 510146778Ssam ipd.len = length; 511146778Ssam ipd.off = 0; 512146778Ssam ipd.nh = nh; 513146778Ssam ipd.advance = 0; 514146778Ssam 515146778Ssam ip_print_demux(ndo, &ipd); 516146778Ssam} 517146778Ssam 518146778Ssam 519127675Sbms/* 52017680Spst * print an IP datagram. 52117680Spst */ 52217680Spstvoid 523146778Ssamip_print(netdissect_options *ndo, 524146778Ssam const u_char *bp, 525146778Ssam u_int length) 52617680Spst{ 527146778Ssam struct ip_print_demux_state ipd; 528146778Ssam struct ip_print_demux_state *ipds=&ipd; 529127675Sbms const u_char *ipend; 530146778Ssam u_int hlen; 531235530Sdelphij struct cksum_vec vec[1]; 532146778Ssam u_int16_t sum, ip_sum; 533111729Sfenner struct protoent *proto; 53417680Spst 535146778Ssam ipds->ip = (const struct ip *)bp; 536146778Ssam if (IP_V(ipds->ip) != 4) { /* print version if != 4 */ 537146778Ssam printf("IP%u ", IP_V(ipds->ip)); 538146778Ssam if (IP_V(ipds->ip) == 6) 539127675Sbms printf(", wrong link-layer encapsulation"); 540127675Sbms } 541146778Ssam else if (!eflag) 542127675Sbms printf("IP "); 54317680Spst 544235530Sdelphij if ((u_char *)(ipds->ip + 1) > ndo->ndo_snapend) { 54517680Spst printf("[|ip]"); 54617680Spst return; 54717680Spst } 54817680Spst if (length < sizeof (struct ip)) { 549146778Ssam (void)printf("truncated-ip %u", length); 55017680Spst return; 55117680Spst } 552146778Ssam hlen = IP_HL(ipds->ip) * 4; 55375118Sfenner if (hlen < sizeof (struct ip)) { 554127675Sbms (void)printf("bad-hlen %u", hlen); 55575118Sfenner return; 55675118Sfenner } 55717680Spst 558146778Ssam ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len); 559146778Ssam if (length < ipds->len) 560127675Sbms (void)printf("truncated-ip - %u bytes missing! ", 561146778Ssam ipds->len - length); 562146778Ssam if (ipds->len < hlen) { 563146778Ssam#ifdef GUESS_TSO 564146778Ssam if (ipds->len) { 565146778Ssam (void)printf("bad-len %u", ipds->len); 566146778Ssam return; 567146778Ssam } 568146778Ssam else { 569146778Ssam /* we guess that it is a TSO send */ 570146778Ssam ipds->len = length; 571146778Ssam } 572146778Ssam#else 573146778Ssam (void)printf("bad-len %u", ipds->len); 574146778Ssam return; 575146778Ssam#endif /* GUESS_TSO */ 576127675Sbms } 577127675Sbms 578127675Sbms /* 579127675Sbms * Cut off the snapshot length to the end of the IP payload. 580127675Sbms */ 581146778Ssam ipend = bp + ipds->len; 582235530Sdelphij if (ipend < ndo->ndo_snapend) 583235530Sdelphij ndo->ndo_snapend = ipend; 584127675Sbms 585146778Ssam ipds->len -= hlen; 58617680Spst 587146778Ssam ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off); 588127675Sbms 589127675Sbms if (vflag) { 590146778Ssam (void)printf("(tos 0x%x", (int)ipds->ip->ip_tos); 591127675Sbms /* ECN bits */ 592146778Ssam if (ipds->ip->ip_tos & 0x03) { 593146778Ssam switch (ipds->ip->ip_tos & 0x03) { 594127675Sbms case 1: 595127675Sbms (void)printf(",ECT(1)"); 596127675Sbms break; 597127675Sbms case 2: 598127675Sbms (void)printf(",ECT(0)"); 599127675Sbms break; 600127675Sbms case 3: 601127675Sbms (void)printf(",CE"); 602127675Sbms } 603127675Sbms } 604127675Sbms 605146778Ssam if (ipds->ip->ip_ttl >= 1) 606241235Sdelphij (void)printf(", ttl %u", ipds->ip->ip_ttl); 607127675Sbms 608127675Sbms /* 609127675Sbms * for the firewall guys, print id, offset. 610127675Sbms * On all but the last stick a "+" in the flags portion. 611127675Sbms * For unfragmented datagrams, note the don't fragment flag. 612127675Sbms */ 613127675Sbms 614172686Smlaier (void)printf(", id %u, offset %u, flags [%s], proto %s (%u)", 615146778Ssam EXTRACT_16BITS(&ipds->ip->ip_id), 616146778Ssam (ipds->off & 0x1fff) * 8, 617172686Smlaier bittok2str(ip_frag_values, "none", ipds->off&0xe000), 618146778Ssam tok2str(ipproto_values,"unknown",ipds->ip->ip_p), 619146778Ssam ipds->ip->ip_p); 620127675Sbms 621172686Smlaier (void)printf(", length %u", EXTRACT_16BITS(&ipds->ip->ip_len)); 622127675Sbms 623127675Sbms if ((hlen - sizeof(struct ip)) > 0) { 624172686Smlaier printf(", options ("); 625146778Ssam ip_optprint((u_char *)(ipds->ip + 1), hlen - sizeof(struct ip)); 626172686Smlaier printf(")"); 627127675Sbms } 628127675Sbms 629235530Sdelphij if (!Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) { 630235530Sdelphij vec[0].ptr = (const u_int8_t *)(void *)ipds->ip; 631235530Sdelphij vec[0].len = hlen; 632235530Sdelphij sum = in_cksum(vec, 1); 633127675Sbms if (sum != 0) { 634146778Ssam ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum); 635127675Sbms (void)printf(", bad cksum %x (->%x)!", ip_sum, 636127675Sbms in_cksum_shouldbe(ip_sum, sum)); 637127675Sbms } 638127675Sbms } 639127675Sbms 640190207Srpaulo printf(")\n "); 641127675Sbms } 642127675Sbms 64317680Spst /* 64417680Spst * If this is fragment zero, hand it to the next higher 64517680Spst * level protocol. 64617680Spst */ 647146778Ssam if ((ipds->off & 0x1fff) == 0) { 648146778Ssam ipds->cp = (const u_char *)ipds->ip + hlen; 649146778Ssam ipds->nh = ipds->ip->ip_p; 65017680Spst 651146778Ssam if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP && 652162021Ssam ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) { 653146778Ssam (void)printf("%s > %s: ", 654146778Ssam ipaddr_string(&ipds->ip->ip_src), 655146778Ssam ipaddr_string(&ipds->ip->ip_dst)); 65656896Sfenner } 657146778Ssam ip_print_demux(ndo, ipds); 658127675Sbms } else { 659127675Sbms /* Ultra quiet now means that all this stuff should be suppressed */ 660127675Sbms if (qflag > 1) return; 66156896Sfenner 662127675Sbms /* 663127675Sbms * if this isn't the first frag, we're missing the 664127675Sbms * next level protocol header. print the ip addr 665127675Sbms * and the protocol. 666127675Sbms */ 667146778Ssam if (ipds->off & 0x1fff) { 668146778Ssam (void)printf("%s > %s:", ipaddr_string(&ipds->ip->ip_src), 669146778Ssam ipaddr_string(&ipds->ip->ip_dst)); 670241235Sdelphij if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL) 671127675Sbms (void)printf(" %s", proto->p_name); 672127675Sbms else 673146778Ssam (void)printf(" ip-proto-%d", ipds->ip->ip_p); 674241235Sdelphij } 67556896Sfenner } 67617680Spst} 67775118Sfenner 67875118Sfennervoid 67975118SfenneripN_print(register const u_char *bp, register u_int length) 68075118Sfenner{ 68175118Sfenner struct ip *ip, hdr; 68275118Sfenner 68375118Sfenner ip = (struct ip *)bp; 68475118Sfenner if (length < 4) { 68575118Sfenner (void)printf("truncated-ip %d", length); 68675118Sfenner return; 68775118Sfenner } 68875118Sfenner memcpy (&hdr, (char *)ip, 4); 68975118Sfenner switch (IP_V(&hdr)) { 69075118Sfenner case 4: 691146778Ssam ip_print (gndo, bp, length); 69298527Sfenner return; 69375118Sfenner#ifdef INET6 69475118Sfenner case 6: 695235530Sdelphij ip6_print (gndo, bp, length); 69698527Sfenner return; 69775118Sfenner#endif 69875118Sfenner default: 69998527Sfenner (void)printf("unknown ip %d", IP_V(&hdr)); 70098527Sfenner return; 70175118Sfenner } 70275118Sfenner} 703127675Sbms 704146778Ssam/* 705146778Ssam * Local Variables: 706146778Ssam * c-style: whitesmith 707146778Ssam * c-basic-offset: 8 708146778Ssam * End: 709146778Ssam */ 710127675Sbms 711127675Sbms 712