print-ip.c revision 276788
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 276788 2015-01-07 19:55:18Z delphij $ 2217680Spst */ 2317680Spst 24276788Sdelphij#define NETDISSECT_REWORKED 2556896Sfenner#ifdef HAVE_CONFIG_H 2656896Sfenner#include "config.h" 2756896Sfenner#endif 2856896Sfenner 29127675Sbms#include <tcpdump-stdinc.h> 3017680Spst 3117680Spst#include <string.h> 3217680Spst 33276788Sdelphij#include "interface.h" 3417680Spst#include "addrtoname.h" 3517680Spst#include "extract.h" /* must come after interface.h */ 3617680Spst 3775118Sfenner#include "ip.h" 38127675Sbms#include "ipproto.h" 3975118Sfenner 40276788Sdelphijstatic const char tstr[] = "[|ip]"; 41276788Sdelphij 42276788Sdelphijstatic const struct tok ip_option_values[] = { 43146778Ssam { IPOPT_EOL, "EOL" }, 44146778Ssam { IPOPT_NOP, "NOP" }, 45146778Ssam { IPOPT_TS, "timestamp" }, 46146778Ssam { IPOPT_SECURITY, "security" }, 47146778Ssam { IPOPT_RR, "RR" }, 48146778Ssam { IPOPT_SSRR, "SSRR" }, 49146778Ssam { IPOPT_LSRR, "LSRR" }, 50146778Ssam { IPOPT_RA, "RA" }, 51172686Smlaier { IPOPT_RFC1393, "traceroute" }, 52146778Ssam { 0, NULL } 53146778Ssam}; 54146778Ssam 5517680Spst/* 5617680Spst * print the recorded route in an IP RR, LSRR or SSRR option. 5717680Spst */ 5817680Spststatic void 59276788Sdelphijip_printroute(netdissect_options *ndo, 60276788Sdelphij register const u_char *cp, u_int length) 6117680Spst{ 62127675Sbms register u_int ptr; 6317680Spst register u_int len; 6417680Spst 65127675Sbms if (length < 3) { 66276788Sdelphij ND_PRINT((ndo, " [bad length %u]", length)); 67127675Sbms return; 68127675Sbms } 6917680Spst if ((length + 1) & 3) 70276788Sdelphij ND_PRINT((ndo, " [bad length %u]", length)); 71127675Sbms ptr = cp[2] - 1; 7217680Spst if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) 73276788Sdelphij ND_PRINT((ndo, " [bad ptr %u]", cp[2])); 7417680Spst 7517680Spst for (len = 3; len < length; len += 4) { 76276788Sdelphij ND_PRINT((ndo, " %s", ipaddr_string(ndo, &cp[len]))); 77276788Sdelphij if (ptr > len) 78276788Sdelphij ND_PRINT((ndo, ",")); 7917680Spst } 8017680Spst} 8117680Spst 82127675Sbms/* 83146778Ssam * If source-routing is present and valid, return the final destination. 84127675Sbms * Otherwise, return IP destination. 85127675Sbms * 86127675Sbms * This is used for UDP and TCP pseudo-header in the checksum 87127675Sbms * calculation. 88127675Sbms */ 89276788Sdelphijstatic uint32_t 90276788Sdelphijip_finddst(netdissect_options *ndo, 91276788Sdelphij const struct ip *ip) 92127675Sbms{ 93127675Sbms int length; 94127675Sbms int len; 95127675Sbms const u_char *cp; 96276788Sdelphij uint32_t retval; 97127675Sbms 98127675Sbms cp = (const u_char *)(ip + 1); 99127675Sbms length = (IP_HL(ip) << 2) - sizeof(struct ip); 100127675Sbms 101127675Sbms for (; length > 0; cp += len, length -= len) { 102127675Sbms int tt; 103127675Sbms 104276788Sdelphij ND_TCHECK(*cp); 105127675Sbms tt = *cp; 106146778Ssam if (tt == IPOPT_EOL) 107146778Ssam break; 108146778Ssam else if (tt == IPOPT_NOP) 109127675Sbms len = 1; 110127675Sbms else { 111276788Sdelphij ND_TCHECK(cp[1]); 112127675Sbms len = cp[1]; 113146778Ssam if (len < 2) 114146778Ssam break; 115127675Sbms } 116276788Sdelphij ND_TCHECK2(*cp, len); 117127675Sbms switch (tt) { 118127675Sbms 119127675Sbms case IPOPT_SSRR: 120127675Sbms case IPOPT_LSRR: 121127675Sbms if (len < 7) 122146778Ssam break; 123276788Sdelphij UNALIGNED_MEMCPY(&retval, cp + len - 4, 4); 124127675Sbms return retval; 125127675Sbms } 126127675Sbms } 127127675Sbmstrunc: 128276788Sdelphij UNALIGNED_MEMCPY(&retval, &ip->ip_dst.s_addr, sizeof(uint32_t)); 129146778Ssam return retval; 130127675Sbms} 131127675Sbms 132235530Sdelphij/* 133235530Sdelphij * Compute a V4-style checksum by building a pseudoheader. 134235530Sdelphij */ 135235530Sdelphijint 136276788Sdelphijnextproto4_cksum(netdissect_options *ndo, 137276788Sdelphij const struct ip *ip, const uint8_t *data, 138276788Sdelphij u_int len, u_int covlen, u_int next_proto) 139235530Sdelphij{ 140235530Sdelphij struct phdr { 141276788Sdelphij uint32_t src; 142276788Sdelphij uint32_t dst; 143235530Sdelphij u_char mbz; 144235530Sdelphij u_char proto; 145276788Sdelphij uint16_t len; 146235530Sdelphij } ph; 147235530Sdelphij struct cksum_vec vec[2]; 148235530Sdelphij 149235530Sdelphij /* pseudo-header.. */ 150276788Sdelphij ph.len = htons((uint16_t)len); 151235530Sdelphij ph.mbz = 0; 152235530Sdelphij ph.proto = next_proto; 153276788Sdelphij UNALIGNED_MEMCPY(&ph.src, &ip->ip_src.s_addr, sizeof(uint32_t)); 154235530Sdelphij if (IP_HL(ip) == 5) 155276788Sdelphij UNALIGNED_MEMCPY(&ph.dst, &ip->ip_dst.s_addr, sizeof(uint32_t)); 156235530Sdelphij else 157276788Sdelphij ph.dst = ip_finddst(ndo, ip); 158235530Sdelphij 159276788Sdelphij vec[0].ptr = (const uint8_t *)(void *)&ph; 160235530Sdelphij vec[0].len = sizeof(ph); 161235530Sdelphij vec[1].ptr = data; 162276788Sdelphij vec[1].len = covlen; 163235530Sdelphij return (in_cksum(vec, 2)); 164235530Sdelphij} 165235530Sdelphij 16656896Sfennerstatic void 167276788Sdelphijip_printts(netdissect_options *ndo, 168276788Sdelphij 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) { 176276788Sdelphij ND_PRINT((ndo, "[bad length %u]", length)); 177127675Sbms return; 178127675Sbms } 179276788Sdelphij ND_PRINT((ndo, " TS{")); 18056896Sfenner hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4; 18156896Sfenner if ((length - 4) & (hoplen-1)) 182276788Sdelphij ND_PRINT((ndo, "[bad length %u]", length)); 183127675Sbms ptr = cp[2] - 1; 184127675Sbms len = 0; 18556896Sfenner if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) 186276788Sdelphij ND_PRINT((ndo, "[bad ptr %u]", cp[2])); 18756896Sfenner switch (cp[3]&0xF) { 18856896Sfenner case IPOPT_TS_TSONLY: 189276788Sdelphij ND_PRINT((ndo, "TSONLY")); 19056896Sfenner break; 19156896Sfenner case IPOPT_TS_TSANDADDR: 192276788Sdelphij ND_PRINT((ndo, "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: 201276788Sdelphij ND_PRINT((ndo, "PRESPEC2.0")); 20256896Sfenner break; 20356896Sfenner case 3: /* IPOPT_TS_PRESPEC */ 204276788Sdelphij ND_PRINT((ndo, "PRESPEC")); 20556896Sfenner break; 206127675Sbms default: 207276788Sdelphij ND_PRINT((ndo, "[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 = " ^ "; 215276788Sdelphij ND_PRINT((ndo, "%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]), 216276788Sdelphij hoplen!=8 ? "" : ipaddr_string(ndo, &cp[len]))); 21756896Sfenner type = " "; 21856896Sfenner } 21956896Sfenner 22056896Sfennerdone: 221276788Sdelphij ND_PRINT((ndo, "%s", ptr == len ? " ^ " : "")); 22256896Sfenner 22356896Sfenner if (cp[3]>>4) 224276788Sdelphij ND_PRINT((ndo, " [%d hops not recorded]} ", cp[3]>>4)); 22556896Sfenner else 226276788Sdelphij ND_PRINT((ndo, "}")); 22756896Sfenner} 22856896Sfenner 22917680Spst/* 23017680Spst * print IP options. 23117680Spst */ 23217680Spststatic void 233276788Sdelphijip_optprint(netdissect_options *ndo, 234276788Sdelphij register const u_char *cp, u_int length) 23517680Spst{ 236146778Ssam register u_int option_len; 237172686Smlaier const char *sep = ""; 23817680Spst 239146778Ssam for (; length > 0; cp += option_len, length -= option_len) { 240146778Ssam u_int option_code; 24117680Spst 242276788Sdelphij ND_PRINT((ndo, "%s", sep)); 243172686Smlaier sep = ","; 244172686Smlaier 245276788Sdelphij ND_TCHECK(*cp); 246146778Ssam option_code = *cp; 247146778Ssam 248276788Sdelphij ND_PRINT((ndo, "%s", 249276788Sdelphij tok2str(ip_option_values,"unknown %u",option_code))); 250172686Smlaier 251146778Ssam if (option_code == IPOPT_NOP || 252146778Ssam option_code == IPOPT_EOL) 253146778Ssam option_len = 1; 254146778Ssam 25575118Sfenner else { 256276788Sdelphij ND_TCHECK(cp[1]); 257172686Smlaier option_len = cp[1]; 258172686Smlaier if (option_len < 2) { 259276788Sdelphij ND_PRINT((ndo, " [bad length %u]", option_len)); 260172686Smlaier return; 261172686Smlaier } 26275118Sfenner } 26317680Spst 264172686Smlaier if (option_len > length) { 265276788Sdelphij ND_PRINT((ndo, " [bad length %u]", option_len)); 266172686Smlaier return; 267172686Smlaier } 268146778Ssam 269276788Sdelphij ND_TCHECK2(*cp, option_len); 270146778Ssam 271146778Ssam switch (option_code) { 27217680Spst case IPOPT_EOL: 27317680Spst return; 27417680Spst 27517680Spst case IPOPT_TS: 276276788Sdelphij ip_printts(ndo, cp, option_len); 27717680Spst break; 27817680Spst 279146778Ssam case IPOPT_RR: /* fall through */ 28017680Spst case IPOPT_SSRR: 28117680Spst case IPOPT_LSRR: 282276788Sdelphij ip_printroute(ndo, cp, option_len); 28317680Spst break; 28417680Spst 28517691Spst case IPOPT_RA: 286172686Smlaier if (option_len < 4) { 287276788Sdelphij ND_PRINT((ndo, " [bad length %u]", option_len)); 288172686Smlaier break; 289172686Smlaier } 290276788Sdelphij ND_TCHECK(cp[3]); 291276788Sdelphij if (EXTRACT_16BITS(&cp[2]) != 0) 292276788Sdelphij ND_PRINT((ndo, " value %u", EXTRACT_16BITS(&cp[2]))); 29398527Sfenner break; 29417691Spst 295146778Ssam case IPOPT_NOP: /* nothing to print - fall through */ 296146778Ssam case IPOPT_SECURITY: 29717680Spst default: 29817680Spst break; 29917680Spst } 30017680Spst } 301127675Sbms return; 302127675Sbms 303127675Sbmstrunc: 304276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 30517680Spst} 30617680Spst 307127675Sbms#define IP_RES 0x8000 308127675Sbms 309276788Sdelphijstatic const struct tok ip_frag_values[] = { 310127675Sbms { IP_MF, "+" }, 311127675Sbms { IP_DF, "DF" }, 312127675Sbms { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */ 313127675Sbms { 0, NULL } 314127675Sbms}; 315127675Sbms 316146778Ssamstruct ip_print_demux_state { 317146778Ssam const struct ip *ip; 318146778Ssam const u_char *cp; 319146778Ssam u_int len, off; 320146778Ssam u_char nh; 321146778Ssam int advance; 322146778Ssam}; 323146778Ssam 324146778Ssamstatic void 325146778Ssamip_print_demux(netdissect_options *ndo, 326146778Ssam struct ip_print_demux_state *ipds) 327146778Ssam{ 328146778Ssam struct protoent *proto; 329235530Sdelphij struct cksum_vec vec[1]; 330146778Ssam 331146778Ssamagain: 332146778Ssam switch (ipds->nh) { 333146778Ssam 334146778Ssam case IPPROTO_AH: 335146778Ssam ipds->nh = *ipds->cp; 336276788Sdelphij ipds->advance = ah_print(ndo, ipds->cp); 337146778Ssam if (ipds->advance <= 0) 338146778Ssam break; 339146778Ssam ipds->cp += ipds->advance; 340146778Ssam ipds->len -= ipds->advance; 341146778Ssam goto again; 342146778Ssam 343146778Ssam case IPPROTO_ESP: 344146778Ssam { 345146778Ssam int enh, padlen; 346146778Ssam ipds->advance = esp_print(ndo, ipds->cp, ipds->len, 347146778Ssam (const u_char *)ipds->ip, 348146778Ssam &enh, &padlen); 349146778Ssam if (ipds->advance <= 0) 350146778Ssam break; 351146778Ssam ipds->cp += ipds->advance; 352146778Ssam ipds->len -= ipds->advance + padlen; 353146778Ssam ipds->nh = enh & 0xff; 354146778Ssam goto again; 355146778Ssam } 356241235Sdelphij 357146778Ssam case IPPROTO_IPCOMP: 358146778Ssam { 359146778Ssam int enh; 360276788Sdelphij ipds->advance = ipcomp_print(ndo, ipds->cp, &enh); 361146778Ssam if (ipds->advance <= 0) 362146778Ssam break; 363146778Ssam ipds->cp += ipds->advance; 364146778Ssam ipds->len -= ipds->advance; 365146778Ssam ipds->nh = enh & 0xff; 366146778Ssam goto again; 367146778Ssam } 368146778Ssam 369146778Ssam case IPPROTO_SCTP: 370276788Sdelphij sctp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len); 371146778Ssam break; 372162021Ssam 373162021Ssam case IPPROTO_DCCP: 374276788Sdelphij dccp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len); 375162021Ssam break; 376241235Sdelphij 377146778Ssam case IPPROTO_TCP: 378172686Smlaier /* pass on the MF bit plus the offset to detect fragments */ 379276788Sdelphij tcp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, 380172686Smlaier ipds->off & (IP_MF|IP_OFFMASK)); 381146778Ssam break; 382241235Sdelphij 383146778Ssam case IPPROTO_UDP: 384172686Smlaier /* pass on the MF bit plus the offset to detect fragments */ 385276788Sdelphij udp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, 386172686Smlaier ipds->off & (IP_MF|IP_OFFMASK)); 387146778Ssam break; 388241235Sdelphij 389146778Ssam case IPPROTO_ICMP: 390146778Ssam /* pass on the MF bit plus the offset to detect fragments */ 391276788Sdelphij icmp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, 392172686Smlaier ipds->off & (IP_MF|IP_OFFMASK)); 393146778Ssam break; 394241235Sdelphij 395146778Ssam case IPPROTO_PIGP: 396146778Ssam /* 397146778Ssam * XXX - the current IANA protocol number assignments 398146778Ssam * page lists 9 as "any private interior gateway 399146778Ssam * (used by Cisco for their IGRP)" and 88 as 400146778Ssam * "EIGRP" from Cisco. 401146778Ssam * 402146778Ssam * Recent BSD <netinet/in.h> headers define 403146778Ssam * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88. 404146778Ssam * We define IP_PROTO_PIGP as 9 and 405146778Ssam * IP_PROTO_EIGRP as 88; those names better 406146778Ssam * match was the current protocol number 407146778Ssam * assignments say. 408146778Ssam */ 409276788Sdelphij igrp_print(ndo, ipds->cp, ipds->len); 410146778Ssam break; 411241235Sdelphij 412146778Ssam case IPPROTO_EIGRP: 413276788Sdelphij eigrp_print(ndo, ipds->cp, ipds->len); 414146778Ssam break; 415241235Sdelphij 416146778Ssam case IPPROTO_ND: 417146778Ssam ND_PRINT((ndo, " nd %d", ipds->len)); 418146778Ssam break; 419146778Ssam 420146778Ssam case IPPROTO_EGP: 421276788Sdelphij egp_print(ndo, ipds->cp, ipds->len); 422146778Ssam break; 423146778Ssam 424146778Ssam case IPPROTO_OSPF: 425276788Sdelphij ospf_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip); 426146778Ssam break; 427146778Ssam 428146778Ssam case IPPROTO_IGMP: 429276788Sdelphij igmp_print(ndo, ipds->cp, ipds->len); 430146778Ssam break; 431146778Ssam 432146778Ssam case IPPROTO_IPV4: 433146778Ssam /* DVMRP multicast tunnel (ip-in-ip encapsulation) */ 434235530Sdelphij ip_print(ndo, ipds->cp, ipds->len); 435276788Sdelphij if (! ndo->ndo_vflag) { 436146778Ssam ND_PRINT((ndo, " (ipip-proto-4)")); 437146778Ssam return; 438146778Ssam } 439146778Ssam break; 440241235Sdelphij 441146778Ssam#ifdef INET6 442146778Ssam case IPPROTO_IPV6: 443146778Ssam /* ip6-in-ip encapsulation */ 444235530Sdelphij ip6_print(ndo, ipds->cp, ipds->len); 445146778Ssam break; 446146778Ssam#endif /*INET6*/ 447146778Ssam 448146778Ssam case IPPROTO_RSVP: 449276788Sdelphij rsvp_print(ndo, ipds->cp, ipds->len); 450146778Ssam break; 451146778Ssam 452146778Ssam case IPPROTO_GRE: 453146778Ssam /* do it */ 454276788Sdelphij gre_print(ndo, ipds->cp, ipds->len); 455146778Ssam break; 456146778Ssam 457146778Ssam case IPPROTO_MOBILE: 458276788Sdelphij mobile_print(ndo, ipds->cp, ipds->len); 459146778Ssam break; 460146778Ssam 461146778Ssam case IPPROTO_PIM: 462235530Sdelphij vec[0].ptr = ipds->cp; 463235530Sdelphij vec[0].len = ipds->len; 464276788Sdelphij pim_print(ndo, ipds->cp, ipds->len, in_cksum(vec, 1)); 465146778Ssam break; 466146778Ssam 467146778Ssam case IPPROTO_VRRP: 468276788Sdelphij if (ndo->ndo_packettype == PT_CARP) { 469276788Sdelphij if (ndo->ndo_vflag) 470276788Sdelphij ND_PRINT((ndo, "carp %s > %s: ", 471276788Sdelphij ipaddr_string(ndo, &ipds->ip->ip_src), 472276788Sdelphij ipaddr_string(ndo, &ipds->ip->ip_dst))); 473276788Sdelphij carp_print(ndo, ipds->cp, ipds->len, ipds->ip->ip_ttl); 474235530Sdelphij } else { 475276788Sdelphij if (ndo->ndo_vflag) 476276788Sdelphij ND_PRINT((ndo, "vrrp %s > %s: ", 477276788Sdelphij ipaddr_string(ndo, &ipds->ip->ip_src), 478276788Sdelphij ipaddr_string(ndo, &ipds->ip->ip_dst))); 479276788Sdelphij vrrp_print(ndo, ipds->cp, ipds->len, 480276788Sdelphij (const u_char *)ipds->ip, ipds->ip->ip_ttl); 481235530Sdelphij } 482146778Ssam break; 483146778Ssam 484147904Ssam case IPPROTO_PGM: 485276788Sdelphij pgm_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip); 486147904Ssam break; 487147904Ssam 488257349Sglebius#if defined(HAVE_NET_PFVAR_H) 489241221Sglebius case IPPROTO_PFSYNC: 490241221Sglebius pfsync_ip_print(ipds->cp, ipds->len); 491241221Sglebius break; 492257349Sglebius#endif 493241221Sglebius 494146778Ssam default: 495241235Sdelphij if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL) 496146778Ssam ND_PRINT((ndo, " %s", proto->p_name)); 497146778Ssam else 498146778Ssam ND_PRINT((ndo, " ip-proto-%d", ipds->nh)); 499146778Ssam ND_PRINT((ndo, " %d", ipds->len)); 500146778Ssam break; 501146778Ssam } 502146778Ssam} 503241235Sdelphij 504146778Ssamvoid 505146778Ssamip_print_inner(netdissect_options *ndo, 506146778Ssam const u_char *bp, 507146778Ssam u_int length, u_int nh, 508146778Ssam const u_char *bp2) 509146778Ssam{ 510146778Ssam struct ip_print_demux_state ipd; 511146778Ssam 512146778Ssam ipd.ip = (const struct ip *)bp2; 513146778Ssam ipd.cp = bp; 514146778Ssam ipd.len = length; 515146778Ssam ipd.off = 0; 516146778Ssam ipd.nh = nh; 517146778Ssam ipd.advance = 0; 518146778Ssam 519146778Ssam ip_print_demux(ndo, &ipd); 520146778Ssam} 521146778Ssam 522146778Ssam 523127675Sbms/* 52417680Spst * print an IP datagram. 52517680Spst */ 52617680Spstvoid 527146778Ssamip_print(netdissect_options *ndo, 528146778Ssam const u_char *bp, 529146778Ssam u_int length) 53017680Spst{ 531146778Ssam struct ip_print_demux_state ipd; 532146778Ssam struct ip_print_demux_state *ipds=&ipd; 533127675Sbms const u_char *ipend; 534146778Ssam u_int hlen; 535235530Sdelphij struct cksum_vec vec[1]; 536276788Sdelphij uint16_t sum, ip_sum; 537111729Sfenner struct protoent *proto; 53817680Spst 539146778Ssam ipds->ip = (const struct ip *)bp; 540146778Ssam if (IP_V(ipds->ip) != 4) { /* print version if != 4 */ 541276788Sdelphij ND_PRINT((ndo, "IP%u ", IP_V(ipds->ip))); 542146778Ssam if (IP_V(ipds->ip) == 6) 543276788Sdelphij ND_PRINT((ndo, ", wrong link-layer encapsulation")); 544127675Sbms } 545276788Sdelphij else if (!ndo->ndo_eflag) 546276788Sdelphij ND_PRINT((ndo, "IP ")); 54717680Spst 548235530Sdelphij if ((u_char *)(ipds->ip + 1) > ndo->ndo_snapend) { 549276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 55017680Spst return; 55117680Spst } 55217680Spst if (length < sizeof (struct ip)) { 553276788Sdelphij ND_PRINT((ndo, "truncated-ip %u", length)); 55417680Spst return; 55517680Spst } 556146778Ssam hlen = IP_HL(ipds->ip) * 4; 55775118Sfenner if (hlen < sizeof (struct ip)) { 558276788Sdelphij ND_PRINT((ndo, "bad-hlen %u", hlen)); 55975118Sfenner return; 56075118Sfenner } 56117680Spst 562146778Ssam ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len); 563146778Ssam if (length < ipds->len) 564276788Sdelphij ND_PRINT((ndo, "truncated-ip - %u bytes missing! ", 565276788Sdelphij ipds->len - length)); 566146778Ssam if (ipds->len < hlen) { 567146778Ssam#ifdef GUESS_TSO 568146778Ssam if (ipds->len) { 569276788Sdelphij ND_PRINT((ndo, "bad-len %u", ipds->len)); 570146778Ssam return; 571146778Ssam } 572146778Ssam else { 573146778Ssam /* we guess that it is a TSO send */ 574146778Ssam ipds->len = length; 575146778Ssam } 576146778Ssam#else 577276788Sdelphij ND_PRINT((ndo, "bad-len %u", ipds->len)); 578146778Ssam return; 579146778Ssam#endif /* GUESS_TSO */ 580127675Sbms } 581127675Sbms 582127675Sbms /* 583127675Sbms * Cut off the snapshot length to the end of the IP payload. 584127675Sbms */ 585146778Ssam ipend = bp + ipds->len; 586235530Sdelphij if (ipend < ndo->ndo_snapend) 587235530Sdelphij ndo->ndo_snapend = ipend; 588127675Sbms 589146778Ssam ipds->len -= hlen; 59017680Spst 591146778Ssam ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off); 592127675Sbms 593276788Sdelphij if (ndo->ndo_vflag) { 594276788Sdelphij ND_PRINT((ndo, "(tos 0x%x", (int)ipds->ip->ip_tos)); 595127675Sbms /* ECN bits */ 596146778Ssam if (ipds->ip->ip_tos & 0x03) { 597146778Ssam switch (ipds->ip->ip_tos & 0x03) { 598127675Sbms case 1: 599276788Sdelphij ND_PRINT((ndo, ",ECT(1)")); 600127675Sbms break; 601127675Sbms case 2: 602276788Sdelphij ND_PRINT((ndo, ",ECT(0)")); 603127675Sbms break; 604127675Sbms case 3: 605276788Sdelphij ND_PRINT((ndo, ",CE")); 606127675Sbms } 607127675Sbms } 608127675Sbms 609146778Ssam if (ipds->ip->ip_ttl >= 1) 610276788Sdelphij ND_PRINT((ndo, ", ttl %u", ipds->ip->ip_ttl)); 611127675Sbms 612127675Sbms /* 613127675Sbms * for the firewall guys, print id, offset. 614127675Sbms * On all but the last stick a "+" in the flags portion. 615127675Sbms * For unfragmented datagrams, note the don't fragment flag. 616127675Sbms */ 617127675Sbms 618276788Sdelphij ND_PRINT((ndo, ", id %u, offset %u, flags [%s], proto %s (%u)", 619146778Ssam EXTRACT_16BITS(&ipds->ip->ip_id), 620146778Ssam (ipds->off & 0x1fff) * 8, 621172686Smlaier bittok2str(ip_frag_values, "none", ipds->off&0xe000), 622146778Ssam tok2str(ipproto_values,"unknown",ipds->ip->ip_p), 623276788Sdelphij ipds->ip->ip_p)); 624127675Sbms 625276788Sdelphij ND_PRINT((ndo, ", length %u", EXTRACT_16BITS(&ipds->ip->ip_len))); 626127675Sbms 627127675Sbms if ((hlen - sizeof(struct ip)) > 0) { 628276788Sdelphij ND_PRINT((ndo, ", options (")); 629276788Sdelphij ip_optprint(ndo, (u_char *)(ipds->ip + 1), hlen - sizeof(struct ip)); 630276788Sdelphij ND_PRINT((ndo, ")")); 631127675Sbms } 632127675Sbms 633276788Sdelphij if (!ndo->ndo_Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) { 634276788Sdelphij vec[0].ptr = (const uint8_t *)(void *)ipds->ip; 635235530Sdelphij vec[0].len = hlen; 636235530Sdelphij sum = in_cksum(vec, 1); 637127675Sbms if (sum != 0) { 638146778Ssam ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum); 639276788Sdelphij ND_PRINT((ndo, ", bad cksum %x (->%x)!", ip_sum, 640276788Sdelphij in_cksum_shouldbe(ip_sum, sum))); 641127675Sbms } 642127675Sbms } 643127675Sbms 644276788Sdelphij ND_PRINT((ndo, ")\n ")); 645127675Sbms } 646127675Sbms 64717680Spst /* 64817680Spst * If this is fragment zero, hand it to the next higher 64917680Spst * level protocol. 65017680Spst */ 651146778Ssam if ((ipds->off & 0x1fff) == 0) { 652146778Ssam ipds->cp = (const u_char *)ipds->ip + hlen; 653146778Ssam ipds->nh = ipds->ip->ip_p; 65417680Spst 655146778Ssam if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP && 656162021Ssam ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) { 657276788Sdelphij ND_PRINT((ndo, "%s > %s: ", 658276788Sdelphij ipaddr_string(ndo, &ipds->ip->ip_src), 659276788Sdelphij ipaddr_string(ndo, &ipds->ip->ip_dst))); 66056896Sfenner } 661146778Ssam ip_print_demux(ndo, ipds); 662127675Sbms } else { 663127675Sbms /* Ultra quiet now means that all this stuff should be suppressed */ 664276788Sdelphij if (ndo->ndo_qflag > 1) return; 66556896Sfenner 666127675Sbms /* 667127675Sbms * if this isn't the first frag, we're missing the 668127675Sbms * next level protocol header. print the ip addr 669127675Sbms * and the protocol. 670127675Sbms */ 671276788Sdelphij if (ipds->off & 0x1fff) { 672276788Sdelphij ND_PRINT((ndo, "%s > %s:", ipaddr_string(ndo, &ipds->ip->ip_src), 673276788Sdelphij ipaddr_string(ndo, &ipds->ip->ip_dst))); 674276788Sdelphij if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL) 675276788Sdelphij ND_PRINT((ndo, " %s", proto->p_name)); 676276788Sdelphij else 677276788Sdelphij ND_PRINT((ndo, " ip-proto-%d", ipds->ip->ip_p)); 678276788Sdelphij } 67956896Sfenner } 68017680Spst} 68175118Sfenner 68275118Sfennervoid 683276788SdelphijipN_print(netdissect_options *ndo, register const u_char *bp, register u_int length) 68475118Sfenner{ 685276788Sdelphij struct ip hdr; 68675118Sfenner 68775118Sfenner if (length < 4) { 688276788Sdelphij ND_PRINT((ndo, "truncated-ip %d", length)); 68975118Sfenner return; 69075118Sfenner } 691276788Sdelphij memcpy (&hdr, bp, 4); 69275118Sfenner switch (IP_V(&hdr)) { 69375118Sfenner case 4: 694276788Sdelphij ip_print (ndo, bp, length); 69598527Sfenner return; 69675118Sfenner#ifdef INET6 69775118Sfenner case 6: 698276788Sdelphij ip6_print (ndo, bp, length); 69998527Sfenner return; 70075118Sfenner#endif 70175118Sfenner default: 702276788Sdelphij ND_PRINT((ndo, "unknown ip %d", IP_V(&hdr))); 70398527Sfenner return; 70475118Sfenner } 70575118Sfenner} 706127675Sbms 707146778Ssam/* 708146778Ssam * Local Variables: 709146778Ssam * c-style: whitesmith 710146778Ssam * c-basic-offset: 8 711146778Ssam * End: 712146778Ssam */ 713127675Sbms 714127675Sbms 715